1、哪些区域需要进行内存回收
在Java运行时区域各部分中,程序计数器、虚拟机、本地方法栈随线程而生,随线程而消亡。而内存回收主要解决Java堆和方法区的内存回收,主要原因在于该部分内存分配和回收是动态的。接口中实现类需要的内存可能不一样,方法中的分支需要的内存可能也不一样。
2、如何判断对象已死呢?
在Java中通过可达性分析算法来判断对象是否存活。
其实现过程是通过“GC Roots”的对象作为起点,从这些节点开始(通过引用链)向下搜索。若一个对象到“GC Roots”没有可达引用链时,则认为此对象不可用,其将会被判定为可回收对象。
在图中object4、object5没有到达“GC Roots”的可达引用链,因此他们会被判定为可回收对象。
3、这些不可达对象是非死不可吗?
其实,宣告他们死亡需要进行两次标记。
第一次标记是在他们没有到达“GC Roots”的可达引用链时。同时他们会被筛选,筛选条件为他们是否有必要执行finalize()方法。若对象未覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,上述两种情况都会被虚拟机认为“没必要执行”。
第二次标记:若该对象有必要执行finalize()方法,则它将会被放置在F-Queue队列中,并在之后由虚拟机自动建立、以低优先级的Finalizer线程去触发这个方法。由于若对象在finalize()方法中执行缓慢或者发生死循环,F-Queue中的其他对象将永久处于等待状态,甚至导致内存回收系统崩溃,因此虚拟机不会承诺等待它执行结束。
finalize()方法是对象逃脱内存回收的最后一次机会,随后GC将对F-Queue队列中的对象进行第二次标记。若对象要拯救自己,则需与引用链上的任意一对象进行关联,即可逃避垃圾回收。若对象未逃脱,其将真被回收。
注意:任何对象的finalize()方法都将会被触发,但如若对象面临再次垃圾回收,其finalize()方法将不会被执行。(finalize()方法可重构)