JVM学习(二) 堆内存 垃圾回收(GC)策略

堆内存概述:堆是 JVM 所管理的最大的一块内存空间,主要用于存放各种类的实例对象。

堆的垃圾回收策略:堆是垃圾回收器管理的主要区域,99%的垃圾回收发生在 堆,另外1%发生在方法区,因此又称之为”GC堆”。JVM对于堆的垃圾回收,采用分代收集的策略。

堆的两个区域:根据堆中对象的存活周期将堆内存分为 新生代 ( Young )、老年代 ( Old )。

堆内存分代的原因:分代是为了优化 GC 性能。如果没分代 GC 需要对 堆内存 所有区域进行扫描。分代后, CG将指定区域(新声代:存储大量朝生夕死的对象)进行回收。这样就可以腾出很大的空间

一、新生代

新生代( Young ):很快就会被GC回收掉的或者不是特别大的对象。

新生代 ( Young )区域:Eden(伊甸园)和两个Survivor(幸存者,分别叫做 Form 和 To)。新创建的对象都分配至 Eden 区中,当经过 GC 后任存活,将其移至 Survivor区中。每当一次 GC过后,存活在 Survivor 区中的对象就会 加一岁 ,当到一定的程度时,就移至 老生代

新生代 GC算法:使用的是复制算法,复制算法的基本思想就是将内存分为两块,每次只用其中一块,当这一块内存用完,就将还活着的对象复制到另外一块上面。这样的话就不会产生内存碎片。

新生代 GC算法 逻辑:在GC开始的时候,对象只会存在于Eden区和名为“From”的Survivor区,Survivor区“To”是空的。紧接着进行GC,Eden区中所有存活的对象都会被复制到“To”,而在“From”区中,仍存活的对象会根据他们的年龄值来决定去向。年龄达到一定值(年龄阈值,可以通过-XX:MaxTenuringThreshold来设置)的对象会被移动到年老代中,没有达到阈值的对象会被复制到“To”区域。经过这次GC后,Eden区和From区已经被清空。这个时候,“From”和“To”会交换他们的角色,也就是新的“To”就是上次GC前的“From”,新的“From”就是上次GC前的“To”。不管怎样,都会保证名为To的Survivor区域是空的。Minor GC会一直重复这样的过程,直到“To”区被填满,“To”区被填满之后,会将所有对象移动到年老代中。

特点: 
a) 新创建的对象都存放在这个区域
b) 此区域较小,GC 频率较高
c) 因算法与对象存储特点,该区域GC效率非常高

二、老生代

老生代( Old) GC算法:复制算法在对象存活率较高的老年代会进行很多次的复制操作,效率很低,所以老年代不适用复制算法。针对老年代对象存活率高的特点,提出了一种称之为”标记-整理算法”。首先标记出所有需要回收的对象 ,然后将所有存活对象都向一端移动,然后直接清理掉端边界以外的内存。

特点: 
a) 将在"新生代"中生存了较长时间的对象转移过来
b) 区域一般要大一些而且增长的速度相对于"新生代"要慢一些
c) 垃圾回收的执行频率也会低很多

三、相关参数

1)-XX:NewSize和-XX:MaxNewSize:用于设置年轻代的大小,建议设为整个堆大小的1/3或者1/4,两个值设为一样大。

2)-XX:SurvivorRatio:用于设置Eden和其中一个Survivor的比值,这个值也比较重要。

3)-XX:+PrintTenuringDistribution:这个参数用于显示每次 GC时Survivor区中各个年龄段的对象的大小。

4).-XX:InitialTenuringThreshol和-XX:MaxTenuringThreshold:用于设置晋升到老年代的对象年龄的最小值和最大值,每个对象在坚持过一次GC之后,年龄就加1。

 

在此附上一位阿里大佬的 老生代增长过快的原因排查

https://www.aliyun.com/jiaocheng/769902.html

你可能感兴趣的:(JAVA)