一、判断可回收对象的算法
1、引用计数法
每个对象配一个引用计数器,被引用一次就+1,引用失效就-1,为0则对象可回收
好处:简单高效
坏处:解决不了循环引用的垃圾对象
2、可达性分析算法
即是否从“GC ROOT”的引用路径可达,不可达的对象就是垃圾了
GC ROOT:
- 本地变量表中引用的对象
- 方法区中静态变量引用的对象
- 方法区中常量引用的对象
- Native方法引用的对象
二、四种引用
1、强引用:被引用的对象永远不会被回收(即程序代码中直接的引用)
2、软引用:内存不够时就将相关对象回收掉(提供了SoftReference类来实现软引用)
3、弱引用、虚引用。。。略
三、finalize()
对象逃离被回收的最后方法,只能使用一次
四、回收方法区(回收常量和类)
可被回收的类:没有实例存在,对应的ClassLoader被回收,java.lang.Class没有被引用。
五、垃圾收集算法
1、标记-清除算法
标记垃圾完成后,统一清除
缺点:1,效率低 2,有空间碎片
2、复制算法
把一块内存分成两块,当其中的一块用完后,将还存活的对象移到另一块上,然后用完的那个块全部清空。
缺点:内存变为了原来的一半
新生代采用的是复制算法,因为对象的存活率很低,将内存分为1个Eden区和两个Survivor区,比例为8:1:1,每次使用Eden区和一块Survivor区,回收时,将存活的对象复制到另一个Survivor区中。
(当Survivor区中的内存不够用时,则通过分配担保机制进入老年代)
3、标记整理算法
即先标记,然后存活的对象向一端移动,紧凑起来,再将端边界以外的内存清空。
六、具体实现
1、枚举根节点
遍历寻找引用很费时,有一组叫OopMap的数据结构可以知道哪些位置有着引用。
2、安全点
执行GC的时间点。
当发生GC时,不直接对线程进行中断操作,而是简单的设置一个中断标志,每个线程运行到Safe Point的时候,主动去轮询这个中断标志,如果中断标志为真,则将自己进行中断挂起。
这里忽略了一个问题,当发生GC时,运行中的线程可以跑到Safe Point后进行挂起,而那些处于Sleep或Blocked状态的线程在此时无法响应JVM的中断请求,无法到Safe Point处进行挂起,针对这种情况,可以使用安全区域(Safe Region)进行解决。
3、安全区域
Safe Region是指在一段代码片段中,对象的引用关系不会发生变化,在这个区域中的任何位置开始GC都是安全的。
1、当线程运行到Safe Region的代码时,首先标识已经进入了Safe Region,如果这段时间内发生GC,JVM会忽略标识为Safe Region状态的线程;
2、当线程即将离开Safe Region时,会检查JVM是否已经完成GC,如果完成了,则继续运行,否则线程必须等待直到收到可以安全离开Safe Region的信号为止;
七、垃圾收集器
参考:http://www.importnew.com/23640.html
八、内存分配与回收策略
待续