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算法

  1. 标记-清除:先标记需要回收的对象,再进行清理,会产生内存碎片;
  2. 标记-整理:先标记,再将所有存活对象向一端移动以解决碎片问题;
  3. 复制算法:将空间分为两部分,每次只使用一块空间,回收时将存活对象复制到另一块空间,再将已使用的那块空间整个清理掉。

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/
作者
Ma Zhichao
发布于
2017年4月10日
许可协议