垃圾收集算法
1.标记清除法:
在标记阶段,程序会检查每个对象是否为活动对象,如果是活动对象,则程序会在对象头部打上标记。在清除阶段,会进行对象回收并取消标志位。
2.复制法:(剩余对象而言)
将内存划分为大小相等的两块,每次只使用其中一块,当这一块内存用完了就将还存活的对象复制到另一块上面,然后再把使用过的内存空间进行一次清理。
3.标记整理法:
让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。
4.分代收集法:
- 新生代使用:复制算法
- 老年代使用:标记 - 清除 算法
判断一个对象是否可被回收
1. 引用计数算法
为对象添加一个引用计数器,当对象增加一个引用时计数器加 1,引用失效时计数器减 1。引用计数为 0 的对象可被回收。
在两个对象出现循环引用的情况下,此时引用计数器永远不为 0,导致无法对它们进行回收。正是因为循环引用的存在,因此 Java 虚拟机不使用引用计数算法。
2. 可达性分析算法
以 GC Roots 为起始点进行搜索,可达的对象都是存活的,不可达的对象可被回收。GC Roots 一般包含以下内容:虚拟机栈中局部变量表中引用的对象、本地方法栈中 JNI 中引用的对象、方法区中类静态属性引用的对象、方法区中的常量引用的对象
3. 方法区的回收
对类的卸载:为了避免内存溢出,在大量使用反射和动态代理的场景都需要虚拟机具备类卸载功能。类的卸载条件很多,该类所有的实例都已经被回收,此时堆中不存在该类的任何实例、加载该类的 ClassLoader 已经被回收。该类对应的 Class 对象没有在任何地方被引用,也就无法在任何地方通过反射访问该类方法。
4. finalize()
如果需要执行该对象的 finalize() 方法,那么就有可能在该方法中让对象重新被引用,从而实现自救。自救只能进行一次,如果回收的对象之前调用了 finalize() 方法自救,后面回收时不会再调用该方法。
全部评论
(0) 回帖