Q:如何确认那些对象的可以回收的
引用计数
如上图,左边为堆,右边为虚拟机栈中的局部变量表,如果堆中的对象相互引用了,那么使用这种方式,即使将引用1跟2断开,对象的引用数量不为0,此时两个堆中的对象无法回收,所以现有的主流jvm虚拟机实现基本不会采用这种方式。
GCRoot(可达性分析)
从如下的GCRoot节点开始向下搜索,当一个对象跟GCRoot节点没有任何引用链的时候,这个对象就是可以回收的。
可以作为GCRoot的有
- 虚拟机栈中的局部变量表中的引用
- 本地方法栈。。
- 方法区中类静态变量引用的对象
- 方法区中常量引用的对象
Q:怎么回收
标记-清除:通过GCRoot找到可回收对象,标记之后清除掉。
会有空间碎片
标记-整理:找到可回收对象之后将它拼接到内存空间的首部
复制:将空间分为两部分A跟B,当A需要回收时,将不回收的对象copy到B,之后清除A。
空间浪费
分代算法:将堆空间分为新生代跟老年代,新生代中的对象在GC的时候有很大一部分需要被回收(IBM-98%),对新生代的GC我们可以改进下复制算法,将区域分为eden(80%)跟两个survivor A跟B(20%);申请空间的时候我们从优先从eden申请,之后从A申请,回收的时候将eden跟A中的不回收对象copy到B,之后清理掉eden跟A。如此。。
对于老年代,每次GC都会有很大部分对象不需要被回收掉,所以更加适合标记-整理算法。