最近在看《深入理解Java虚拟机》(第三版)这本书,小弟发现有几个问题比较困惑。
一、为啥对象的全局变量不能作为GC Roots的对象
二、如果一个对象没有覆盖finalize()方法,那么这个对象是否就不会被二次标记?
最近在看《深入理解Java虚拟机》(第三版)这本书,小弟发现有几个问题比较困惑。
一、为啥对象的全局变量不能作为GC Roots的对象
二、如果一个对象没有覆盖finalize()方法,那么这个对象是否就不会被二次标记?
1.第一个问题解释起来有点拗口,我个人认为用作GCRoot的对象,都是可以准确判断这个对象一定有被使用,或者对象所在区域不容易被GC的,你看你图上的那些作为GCRoot的对象,都有这个特性
①虚拟机栈引用的对象,虚拟机的栈帧是随着方法调用而入栈,方法结束而出栈的,方法调用的时候那些用到的对象肯定是有在使用吧,所以肯定可以作为GCroot
②剩下的那些作为GCroot的差不多也是这个道理,方法区加载的类一般也很少会被GC,所以自然也可以作为GCroot
你的疑惑大概就在于为什么局部变量都可以,为什么全局变量不可以,事实上①中也说明了,局部变量可以是因为栈帧随着方法调用结束而出入栈,这一点可以判断引用的对象是否在使用,而全局变量包含在对象中,何时使用,是否在使用并没有可以依据的标准,因此不可以作为GCroot
2.我觉得原文的意思大概是,如果没有覆盖finalize()方法的话,就表示这个对象已经“死亡”了是会直接标记回收的,可以结合标记-清除算法来看,标记的本质是为了找出要回收的对象,之所以进行二次标记,是为了给一些实现了finalize()方法的类的一次运行该方法的机会,这些实现了finalize()方法会在第一次标记过程中放在F-Queue队列中而不进行标记,如果执行finalize()方法后该对象和GCroot产生了关联,那么对象就会避免被回收,重新存活,如果执行finalize()方法还是没有和GCroot有关联,那么就会被标记回收
3 回答2.6k 阅读✓ 已解决
3 回答4.1k 阅读✓ 已解决
8 回答3.7k 阅读
4 回答2.8k 阅读✓ 已解决
2 回答2.7k 阅读✓ 已解决
3 回答2.5k 阅读✓ 已解决
4 回答1.9k 阅读
1.虚拟机栈中的引用,如果有成员变量,也包含了成员变量吧
2.我当时的理解是如果确定"不需要执行"会被立刻二次标记,总不能因为没覆盖finalize就多活一个轮回。当然是属于个人理解。