工作目的
找到堆中无用的对象,并将这些对象所占用的空间回收,重新使用
算法思路
对象组成集合,或者树状结构,从根部开始找
能找到的都是存活对象,找不到的就是应该被回收的
判断存活
可用计数:每个对象有一个引用计数,新增引用加1,释放减1,计数为0时可回收。无法解决对象相互引用的问题
可达性分析:从GC Roots开始搜索,所走过的路径叫引用链。当一个对象到GC Roots直接没有引用链时,即对象无引用,不可达,可回收
新域会被分为3个部分:第一个部分叫Eden。(伊甸园??可能是因为亚当和夏娃是人类最早的活动对象?),另两个部分称为辅助生存空间(幼儿园),我这里一个称为A空间(From sqace),一个称为B空间(To Space)。
堆中新域的copying算法
对于新生成的对象,都放在Eden中;当Eden充满时(小孩太多了),GC将开始工作,首先停止应用程序的运行,开始收集垃圾;
把所有可找到的对象都复制到A空间中,一旦当A空间充满,GC就把在A空间中可找到的对象 都复制到B空间中(会覆盖原有的存储对象),当B空间满的时间,GC就把在B空间中可找到的对象都复制到A空间中,AB在这个过程中互换角色;
在活动对象经过一定次数的GC操作后,这些活动对象就会被放到旧域中,对于这些活动对象,新域的幼儿园生活结束了。
新域为什么要这么折腾?应用程序生成的绝大部分对象都是短命的,copying算法最理想的状态是,所有移出Eden的对象都会被收集,因为这些都是短命鬼,经过一定次数的GC后应该被收集。那么移入到旧域的对象都是长命的,这样可以防止AB空间的来回复制影响应用程序。
实际上这种理想状态是很难达到的,应用程序中不可避免地存在长命的对象,copying算法的发明者要这些对象都尽量放在新域 中,以保证小范围的复制,压缩旧域的开销可比新域中的复制大得多。
旧域的tracing算法
称为标记-清除-压缩收集器,注意,这有一个压缩,这是个开销挺大的操作。
算法详细可以:https://www.cnblogs.com/ityouknow/p/5614961.html
young generation比例越大,不一定最好。
将young的大小设置为大于总堆大小的一半时会造成效率低下。如果设置得过小,又会因为young generation收集程序不得不频繁运行而造成瓶颈。
总结
1.JVM堆的大小决定了GC的运行时间。如果JVM堆的大小超过一定的限度,那么GC的运行时间会很长。
2.对象生存的时间越长,GC需要的回收时间也越长,影响了回收速度。
3.大多数对象都是短命的,所以,如果能让这些对象的生存期在GC的一次运行周期内,wonderful!
4.建立与释放 对象的速度决定了垃圾收集的频率。
5.如果GC一次运行周期超过3-5秒,这会很影响应用程序的运行,如果可以,应该减少JVM堆的大小了。
6.前辈经验之谈:通常情况下,JVM堆的大小应为物理内存的80%。
参考:https://blog.csdn.net/jiafu1115/article/details/7024323