(JDK1.8)JVM GC整理——堆

一、判断对象是否消亡的算法

1、引用计数算法 —— 因为无法解决对象直接相互引用的问题,因此主流的java虚拟机没有选用此方法

基本思想:为每一个对象添加一个引用计数器,每当有一个地方引用这个对象时,计数器值加1,当引用失效时,计数器值减1;任何时刻计数器的值为0的对象都是可被回收对象。

 

2、可达性分析法

基本思想:将一系列被称为GC Roots的变量作为初始的存活对象集合,然后从该集合出发,所有能被该集合引用到的对象,将其加入到集合中,不能被该集合引用到的对象,则宣告它们死亡。

GC Roots : 是一些由堆外指向堆内的引用

一般而言GC Roots包括但不限于以下几种:

Java 方法栈桢中的局部变量;

已加载类的静态变量;

JNI handles;

已启动且未停止的 Java 线程

 

二、堆内存分布

1、新生代:

新生代按照8:1:1的比例分为Eden(伊甸区)和两个幸存区Survivor(from和to)

2、老年代

 

三、GC算法

1、标记清除:

标记清除是最早开发出来的算法。从根开始将可能被引用的对象用递归的方式进行标记,然后将没有被标记的对象作为垃圾进行回收

2、标记整理:

标记整理又称为标记压缩,是标记清除的变种。因为标记清除会造成很多内存碎片,标记整理就是将标记清除后的内存进行碎片整理

3、复制收集

将可用内存按容量划分为大小相等的两块区域,每次只使用其中一块,当这一块内存用完后,将该内存中所有存活的对象复制到另外一块内存上,然后把已使用过的内存一次性清理掉。

 

四、对象分配原则

1、新创建的对象优先分配到Eden区,如果Eden空间不足时,虚拟机执行一次Minor GC

2、大对象直接进入老年代——大对象是指需要大量连续内存空间的对象。这样做的目的是为了避免Eden区和两个Survivor区发生大量的内存拷贝

3、长期存活的对象进入老年代——虚拟机为每一个对象定义了一个年龄计数器,如果经历了一次Minor GC对象会进入Survivor区,之后每经历一次Minor GC,对象年龄加1,直到达到年龄阀值进入老年代

4、动态判断对象的年龄——如果Survivor区相同年龄的所有对象的内存大小总和大于Survivor内存空间的一半,则大于或等于该年龄的对象进入老年代

5、空间分配担保——每次进行Minor GC时,JVM会计算Survivor区进入老年代对象的内存大小,如果这个值大于老年代剩余内存空间大小,则进行一次Full GC;如果小于,则检查HandlePromotionFailure设置,如果true,则只进行Minor GC,如果false,则进行Full GC

 

五、GC策略

新生代可用策略

1、Serial Copying——串行GC

2、ParNew——并行GC

3、Parallel Scavenge——并行回收GC

老年代可用策略

1、Serial MSC——串行GC

2、Parallel MSC——并行GC

3、CMS——并发GC

 

G1收集器——引入分区的思路,弱化了分代的概念

 

GC策略+GC算法实现GC功能

 

六、GC流程

1、新创建的对象进入新生代Eden区,Eden区判断内存是否满了,如果满了,则执行Minor GC,将Eden区和Survivor from区存活的对象复制到 Survivor to区,清除Eden区和Survivor from区

2、在执行Minor GC后,Survivor to区中,对象年龄达到阀值对象移动到老年代,如果老年代剩余的内存空间小于Survivor to区移动过来的对象大小,则触发Full GC

3、如果触发Full GC后内存仍然不足,则抛出OutOfMemeryError异常

posted @ 2020-07-09 11:16  如若千夫所指  阅读(1769)  评论(0编辑  收藏  举报