垃圾回收机制

2018-07-16  本文已影响0人  胖瘦馒头

垃圾收集算法与GC

①标记--清除算法(老生代)
首先标记出所有需要回收的对象,在标记完后统一回收掉所有被标记的对象。
②复制算法(新生代)
将可用内存分为一块较大的Eden区和两块较少的Survivor(from和to)区,每次使用Eden和其中的一块Survivor(from)。当进行GC的时候,Eden区所有存活的对象都会被复制到Survivor(to),而对于Survivor(from)区,仍然存活的对象会根据他们的年龄值(每个对象定义了一个对象年龄计数器,从Eden到Survivor变为1,之后的每次GC过后,依旧存活的对象年龄+1)来决定去向,年龄达到一定值(默认15,可以设置-XX:MaxTenuringThreshold)的对象会被移动到老年代(特例:如果在Survivor区中相同年龄的所有对象大小的总和大于Survivor空间的一半,年龄大于或者等于改年龄的对象就可以直接进入老年代),没有到达阙值的对象会被复制到Survivor(to)。这次GC之后,Eden区和Survivor(from)都已经被清空。等到下一次GC,上一次的To区就是这一次的From区,上一次的From区就是这一次的To区;Minor GC会一直重复这个过程,知道To区域被填满;To区域被填满之后,会将所有的对象移动的老年代之中。

③标记--整理算法(老年代)
根据老年代存活率较高的情况下,提出了标记--整理算法,标记过程与①是一样的,但是整理过程则是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存;

内存分配与回收策略

1.对象优先在Eden区进行分配。当Eden区没有足够的空间进行分配的时候,JVM会发起一次Minor GC(新生代GC)
2.大对象直接进入老年代(-XX:PretenureSizeThreshold来设置大对象的阙值,可以令大于这个设置值的对象直接在老年代分配,目的是为了减少新生代和老年代之间发生大量的内存拷贝)
3.长期存活的对象将进入老年代(默认15,-XX:MaxTenuringThreshold
4.动态年龄判断,如果在Survivor空间中相同年龄的所有对象的大小的总和大于Survivor空间的一半,年龄大于或者等于改年龄的对象就可以直接进入老年代
5.空间分配担保:在发生Minor GC时,JVM会检测之前每次晋升到老年代的平均大小是否大于老年代的剩余空间,如果大于,则改为一次Full GC。如果小于,则查看HandlePromotionFailure设置是否允许担保失败。如果允许,则只会进行Minor GC,如果不允许,则还是会进行一次Full GC;

finalize() 执行过程

如果某个对象在进行根搜索后发现没有GC Roots相连接的引用链,那么GC就会判断该对象是否覆盖了finalize()方法,如果未覆盖,则直接将其回收。如果该对象有覆盖finalize()方法,且该对象从未执行过finalize()方法,则会将该对象放入F-Queue队列,由一低优先级线程执行该队列中对象的finalize()方法,执行finalize()方法完毕之后,GC会再次判断该对象是否可达,如果不可达,则进行回收,如果可达,则对象“复活”(任何一个对象的finalize()方法都只会被JVM自动调用一次,如果对象面临下一次回收,它的finalize()方法是不会被再次执行的)
无用的类

类要满足一下三点才能成为“无用的类”

1)-XX:NewSize和-XX:MaxNewSize

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

2)-XX:SurvivorRatio

用于设置Eden和其中一个Survivor的比值,这个值也比较重要。

3)-XX:+PrintTenuringDistribution

这个参数用于显示每次Minor GC时Survivor区中各个年龄段的对象的大小。

4).-XX:InitialTenuringThreshol和-XX:MaxTenuringThreshold

用于设置晋升到老年代的对象年龄的最小值和最大值,每个对象在坚持过一次Minor GC之后,年龄就加1。
上一篇 下一篇

猜你喜欢

热点阅读