Learn && Live
虚度年华浮萍于世,勤学善思至死不渝
前言
Hey,欢迎阅读Connor学JVM系列,这个系列记录了我的JVM基础知识学习、复盘过程,欢迎各位大佬阅读斧正!原创不易,转载请注明出处:http://t.csdn.cn/l2sBr,话不多说我们马上开始!
判断可以进行垃圾回收的方法
1.引用计数算法
在对象中添加一个引用计数器
(1)每当有一个地方引用它时,计数器值 + 1
(2)当引用失效时,计数器值 - 1
(3)任何时刻计数器为0的对象就是不可能再被使用的
特殊情况下需要配合大量额外处理才能保证正确地工作,如单一的引用计数很难解决对象之间相互引用的问题
2.可达性分析算法
通过一系列GC Roots根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,搜索过程走过的路径称为引用链,如果某个对象到GC Roots之间没有任何引用链相连,即从GC Roots到该对象不可达,则证明此对象是不可能再被使用的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hpzoIiot-1658108100814)(F:\yhy925\dailylife\Work\1.Java\JVM\Resources\3.垃圾收集器\1.可达性分析.png)]
可达性分析与finalize()
但这样的对象还暂时处于“缓刑”阶段
(1)该对象在进行可达性分析后发现没有与GC Roots相连的引用链,那它会被第一次标记
(2)进行一次筛选,根据该对象是否覆盖了finalize()方法或finalize()方法已经被虚拟机调用过,来判断是否需要执行finalize()
- 不需要执行,即对象没有覆盖finalize()方法或finalize()方法已经被虚拟机调用过
- 需要执行,将该对象放在F-Queue队列中,并在稍后一个由虚拟机自动建立的、低调度优先级的Finalizer线程中执行finalize()方法。这里的执行只是指调用该方法,并不保证等待它运行结束,以防finalize()执行缓慢导致系统崩溃
(3)收集器会对F-Queue中的对象进行第二次标记,如果对象要在finalize()中成功拯救自己——重新与引用链上的任何一个对象建立关联,如将this赋值给某个类变量或者对象的成员变量,那在第二次标记时它将被移出“即将回收”的集合,否则仍会被回收
但finalize()运行代价大,不确定性大,无法保证各个对象的调用顺序,不推荐使用
可作为GC Roots的对象
(1)栈帧的本地变量表中引用的对象,如方法参数、局部变量等
(2)在方法区中类static属性引用的对象,如引用类型的static变量
(3)在方法区中常量引用的对象,如字符串常量池中的引用
(4)在本地方法栈中JNI引用的对象
(5)JVM内部的引用,如基本数据类型对应的Class对象、系统类加载器、一些常驻的异常对象(NPE、OOM)
(6)所有被同步锁持有的对象