Java虚拟机在执行Java程序的过程当中会把它所管理的内存划分为若干个不一样的数据区域。这些区域都有各自的用途,有的区域是线程共享的,有的区域是线程隔离的。以下图:java
程序计数器(Program Counter Register)是一块较小的内存空间,它能够看作是当前线程所执行的字节码的行号指示器。字节码解释器工做时就是经过这个计数器的值来选取下一条须要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都须要依赖这个计数器来完成。缓存
程序计数器是线程私有的内存区域,保证线程切换后能恢复到正确的执行位置。spa
执行Java方法的时候,这个计数器记录的是正在执行的虚拟机字节码的指令的地址;执行native方法的时候,计数器的值为空(null)。线程
Java虚拟机栈(Java Virtual Machine Stacks)描述的是Java方法执行的内存模型:每一个方法在执行的同时都会建立一个栈帧(Stack Frame)用于存储局部变量表、操做数栈、动态连接、方法出口灯信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。3d
Java虚拟机栈也是线程私有的内存区域,生命周期和线程相同。orm
栈帧对象
在活动线程中,只有虚拟机栈顶的栈帧才是有效的,称为当前栈帧(Current Stack Frame),这个栈帧所关联的方法称为当前方法(Current Method)。执行引用所运行的全部字节码指令都只针对当前栈帧进行操做。栈帧的概念结构以下图所示:blog
java虚拟机栈能够抛出以下异常:生命周期
本地方法栈与虚拟机栈的做用是类似的,它们的区别是:进程
与虚拟机栈同样,本地方法栈也会抛出StackOverflowError和OutOfMemoryError。
栈表明了处理逻辑,而堆表明了数据。
Java堆是Java虚拟机所管理的内存最大的一块,也是垃圾收集器管理的主要区域。
Java堆是全部线程共享的,堆中的共享常量和缓存能够被全部栈访问,节省了空间。
为了更好的回收内存,或者更好的分配内存,将Java堆细分为新生代和老年代。
关于每一个区如何回收内存,什么时候回收内存在下一篇中再总结。
堆的大小也是能够调整的,能够经过虚拟机参数-Xmx和-Xms控制。一样,在该区域,若是没有内存分配给对象实例,而且堆也没法再扩展,会抛出OutOfMemoryError异常。
方法区主要用来存储已经被JVM加载的类信息、常量、静态变量等。
在过去(当自定义类加载器使用不广泛的时候),类几乎是“静态的”而且不多被卸载和回收,所以类也能够被当作“永久的”。另外因为类做为JVM实现的一部分,它们不禁程序来建立,由于它们也被认为是“非堆”的内存。
方法区也是全部线程共享的内存区域。
方法区和Java堆同样,也是须要进行垃圾回收的,该区域的内存回收目标主要是针对常量池的回收的和对类型的卸载。
当方法区没法知足内存分配需求时,将抛出OutOfMemoryError异常。
永久代是Hotspot中的一个概念,其余JVM的实现未必有,例如JRockit就没有(只要不触碰进程可用内存上限就不会出问题)。Hotspot使用在内存中划分出一块区域来存储类的元信息、类变量以及内部字符串等,称为永久代,把它做为方法区来使用。
永久代是一段连续的内存空间,咱们在JVM启动以前能够经过设置-XX:MaxPermSize的值来控制永久代的大小,32位机器默认的永久代的大小为64M,64位的机器则为85M。永久代的垃圾回收和老年代的垃圾回收是绑定的,一旦其中一个区域被占满,这两个区都要进行垃圾回收。
Hotspot在Java8中将类的元数据移到了一个与堆不相连的本地内存区域,这个区域就是元空间。
因为类的元数据分配在本地内存中,元空间的最大可分配内存就是系统可用内存空间。用户能够经过-XX:MaxMetaspaceSize为元空间设置一个空间可用最大值,若是不进行设置,JVM会根据类的元数据大小动态增长元空间的容量。
每个类加载器的存储区域都称做一个元空间,全部的元空间合在一块儿就是咱们一直说的元空间。当一个类加载器被垃圾回收器标记为再也不存活,其对应的元空间会被回收。在元空间的回收过程当中没有重定位和压缩等操做。可是元空间内的元数据会进行扫描来肯定Java引用。
元空间虚拟机负责元空间的分配,其采用的形式为组块分配。组块的大小因类加载器的类型而异。在元空间虚拟机中存在一个全局的空闲组块列表。当一个类加载器须要组块时,它就会从这个全局的组块列表中获取并维持一个本身的组块列表。当一个类加载器再也不存活,那么其持有的组块将会被释放,并返回给全局组块列表。
元空间虚拟机采用了组块分配的形式,同时区块的大小由类加载器类型决定。类信息并非固定大小,所以有可能分配的空闲区块和类须要的区块大小不一样,这种状况下可能致使碎片存在。元空间虚拟机目前并不支持压缩操做,因此碎片化是目前最大的问题。
参考资料: