JVM内存模型
JVM内存区域划分
内存区域划分图
各区域说明
程序计数器(Program Counter Register)
存储下一条要执行的字节码指令,线程私有
JAVA虚拟机栈
线程私有,每个方法被执行时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法被调用直至执行完的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。局部变量表
存储了编译期可知的各种基本的数据类型(boolean,byte,char,short,int,float,double,long),对象引用和returnAddress类型(指向了一条字节码指令的地址)。
本地方法栈
与栈类似,区别是虚拟机栈为执行JAVA方法(也就是字节码)服务,而本地方法栈为虚拟机使用到的Native方法服务。
JAVA堆
线程共享的一块内存区域,用于存放对象实例。是GC的主要区域,因此也被称为GC堆。
方法区
线程共享,存储已经被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。也被称为永久代。
垃圾回收(GC)
GC区域主要为:
- JAVA堆
- 方法区:主要回收两部分内容,废弃常量和无用的类,回收的效率较低。
以下所指的GC等同于JAVA堆的回收。
GC算法
- 标记-清除:先标记需要回收的对象,再进行清理,会产生内存碎片;
- 标记-整理:先标记,再将所有存活对象向一端移动以解决碎片问题;
- 复制算法:将空间分为两部分,每次只使用一块空间,回收时将存活对象复制到另一块空间,再将已使用的那块空间整个清理掉。
JAVA堆的内存划分
现在主要使用分代收集策略,将堆分为老年代和新生代,新生代又分为eden空间和survivor空间(8:1)。老年代采用标记-整理算法,新生代采用复制算法。
内存分配与回收策略
- 对象优先分配在Eden区,当Eden区没有足够空间进行分配时,虚拟机将进行一次Minor GC;
- 大对象在分配时直接进行老年代,长期存活的对象进行老年代
- Minor GC时,JVM会检测之前进行到老年代的平均大小是否大于老年代的剩余空间,如果大于则进行一次Full GC, 如果小于,还要看是否允许担保失败,如果允许则进行Minor GC, 否则进行Full GC.
参考文献
- 深入理解JAVA虚拟机-周志明
JVM内存模型
http://yoursite.com/2017/04/10/jvm_memory_model/