1,哪些内存需要回收?
判定哪些对象需要回收,对象存活判定算法有两种:
1,引用计数算法:给对象添加一个引用计数器,对象每被引用一次,引用计数器值就加一,引用失效减一,任何时刻当计数值为0的对象就是不能再被使用的。
这个方法有循环引用的问题,不采用.
2,可达性分析算法:对象和GC Roots之间有引用链时便是可达的,当不可达时,对象便可被回收。
2,可作为GCRoots的对象:
1,虚拟机栈中引用的对象
2,方法区中类静态属性引用的对象
3,方法区中常量引用的对象
4,本地方法栈JNI引用的对象
3,如何进行垃圾回收?
垃圾收集算法:
1,标记--清除算法:
先标记然后统一回收,但是会产生大量内存碎片。
2,复制算法:
80%的Eden,两个10%的Survivor,对象存放在Eden和一个Survivor区中,当发生MinorGC后仍然存活的对象需要复制到另一个Survivor区中,此时这个S区和E区作为存放对象的地方。如果Survivor区无法容纳存活的对象,则需要老年代进行分配担保,直接进入老年代。前提是老年代本身得有容纳那些对象的空间,一共有多少对象存活下来再实际完成内存回收之前是无法明确知道的,所以只好取之前每一次回收晋升到老年代对象容量的平均值作为经验值,来决定是否进行Full GC来让老年代腾出更多空间。
取平均值的方法不是一个100%可用的方法,如果对象突增,远远高于平均值,就会导致担保失败。但是担保失败后还是会重新发起一次Full GC。
3,标记--整理算法:
复制算法在对象存活率很高的时候,效率很低。所以老年代采用标记整理算法:先标记,然后让所有存活的对象往一端移动,直接清理掉端边界以外的内存。
4,分代收集算法:
将java堆分为新生代和老年代,新生代使用复制算法,老年代使用标记--清除或标记--整理算法。