jvm垃圾回收原理

堆内存是垃圾回收的主要管理区域

jvm的堆为什么要分代呢?


因为如果不分代,所有都new出来的数据全部都往堆里面放,很容易导致堆满,堆满后,要进行垃圾回收,因为不分区,要回收的区域大,导致垃圾回收时间长(我们知道在垃圾回收期间,Java程序是不工作的),如果分区,年轻代和老年代

年轻代和老年代的比例是3:5,YGC的时间很快。所以分区比不分区要好。

 

堆内存的分区:

年轻代:伊甸园(eden)和两个存活区(两个存活区s0,s1大小相等,位置互换)

老年代

YGC原理(只清理伊甸园和存活区):

1)Java程序new出来的对象和数组,优先进入伊甸园区,当伊甸园区满后,触发YGC,垃圾回收器判断在伊甸园区的对象是否还存在引用,如果存在引用,说明该对象还存活,如果没有引用,则证明该对象是垃圾,把有引用的对象挪到其中一个存活区,没有引用的对象则进行垃圾回收,垃圾回收后,伊甸园区空了。

2)当伊甸园再次满了的时候,触发YGC,垃圾回收器,判断伊甸园和存活区s0的对象是否存在引用(假设是s0有对象,s1为空),就把伊甸园和s0中有引用的对象放到s1中,其他没有引用的对象就进行垃圾回收,垃圾回收后,伊甸园和s0都空了,对象在s1中。

对象什么时候回进行老年代:

1)大对象直接进入老年代(什么是大对象,在jvm参数设置中有大对象大小设置,如果对象超过设置,就直接进行老年代,为什么设置大对象直接进入老年代呢?因为如果不设置大对象直接进行老年代,大对象进入伊甸园区,就会导致伊甸园区满了,引起频繁的YGC)

2)长期存活的对象进入老年代(jvm中有参数可以设置,默认参数是age=15,满15次后,下一次ygc,如果该对象还存在,就直接进入老年代)

3)对象动态分配原则(针对存活区)

例如 s0------a:4,b:4,c:5,d:1,e:2,

当相同age的大小占s0的一半以上,egage=4a+b>=s0/2  就把age>=4的全部放到老年代(在下一次YGC的时候)

Eg:是否会存在没有age大于存活区的一半,,但是总的age加起来超过了存活区的内存?(官方没有这种情况的解释,应该不会存在这种情况)

什么时候回引起FGC:

 

1.空间担保原则失败

2.老年代满了

3.代码里面显式sys.GC  runtime.GC

4、非堆内存满

5jmap  dump 触发

6RMI框架会定时显式调用sys.GC

 

什么是空间担保原则:

 

YGC时,根据历史情况,判断老年代的区域是否满了。。如果满了就进行FGC所有的区域都清:eden、存活区,老年代。。所以比较耗时,尽量避免fullGC

 

各分区的比例:

年轻代:老年代比例   3:5

伊甸园:存活区s0:存活区s1  比例    8:1:1

 

如何控制YGC和FGC的频率?

 

YGC不能控制(可以控制时间:要短)

 

FGC通过增加fullGC的间隔时间控制

 

 

注意:在jvm进行YGC和FGC时,Java程序是暂停运行的

 

 

Java虚拟机内存FULLGC频率

 

2G内存一般是半小时一次

 

16G内存一般是一天一次

 

 

 

 

 

 

posted @ 2018-01-09 21:53  秃头小怪兽  阅读(78)  评论(0编辑  收藏  举报