基于Hotspot的VM内存模型及GC理解

Hotspot VM内存模型:主要分为栈、堆、方法区

栈空间:主要分为Java虚拟机栈和本地方法栈,其中Java虚拟机栈的生命周期与当前线程相同。每个方法在执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链表、方法出口信息等。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。本地方法栈主要是指执行JNI方法的栈空间。栈中存储的数据包括基本数据类型的值或者该对象在堆空间的地址信息。

堆、方法区:(Generation management)HotSpot VM将堆分为三代,其中年轻代,年老代,永久代(即方法区)

年轻代:存放大多数对象。

           年轻代主要由Eden和两个survivor组成,其中from survivor用于存放经过GC仍存活的数据,to survivor一直都是空的。

大多数对象都直接分配在Eden里面。如下图所示:


年老代:存放大对象(直接分配在年老代)或者经过几次GC仍然存活的对象。

永久代:主要用于存放metadata,包括对class和method以及其描述信息。

GC策略:

1、Serial Collector(串行收集器):stop-the-world and copying collector,主要用于客户端应用。启用方法-XX:+UseSerialGC

年轻代:


如上图所示:Eden中存活的对象复制进入to survivor,其中大对象直接复制进年老代。from survivor中相对年轻的存活对象复制进入to survivor,年老的对象复制进年老代。在一次GC执行之后,清空Eden和from survivor,互换from survivor和to survivor。执行完GC后将年轻代将会变成下图所示:


年老代:


如上图所示:采用mark-sweep-compact(标记-清楚-压缩)算法,将仍存活的对象移到一侧。

2、Parallel Collector(并行收集器):stop-the-world and copying collector,主要用于多个cpu对时间要求不高的应用。启用方法-XX:+UseParallelGC

年轻代:


如上图所示:主要区别于串行收集器是多个cpu同时进行标记回收。

年老代:

与串行收集器相同。

3、Parallel Compacting Collector(并行压缩收集器):stop-the-world and copying collector,主要用于多核,停顿时间少于并行收集器,用法-XX:+UseParallelOldGC. 

年轻代:

   与并行收集器相同。

年老代:

  先将该generation分为固定大小的regions,在marking阶段,并行的标记出并更新所有存活对象的位置和大小;在汇总阶段,从左到右计算出每个region的存活对象率,找到一个位置dense prefix,其左边的region所有对象位置不动,右边的所有region压缩释放dead对象,此步骤单核完成;压缩阶段,将右边的存活对象复制到前面需要填充的region中,释放右边region。

4、Concurrent Mark-Sweep (CMS) Collector(并发标记清除收集器):主要用于多核要求响应时间快,并且容忍一个cpu单独做mark不执行其他线程。用法-XX:+UseConcMarkSweepGC

年轻代:

与并行收集器相同。

年老代:


如上图所示:短暂停顿标记所有可达的root对象,然后并发的标记其他存活的对象,最后并行的重新标记在并发标记时间的改变的对象,释放dead对象空间,收集结束不做压缩工作,收集执行后如下:


GC如何标记存活对象:

可达算法:

以GC roots为起点,从上往下找引用链,找不到引用的对象即为不可达对象。


其中可做为GC roots的节点为:

  1. 虚拟机栈(栈桢中的本地变量表)中的引用的对象
  2. 方法区中的类静态属性引用的对象
  3. 方法区中的常量引用的对象
  4. 本地方法栈中JNI(Native方法)的引用的对象
阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页