小目标之读懂jvm—垃圾回收时的对象死亡判定

断了今生、忘了曾经 提交于 2020-01-20 00:09:38

紧接着之前的阅读进度,第三章讲述了GC(垃圾收集)算法与几种垃圾收集器以及对象创建和GC后的内存分配策略。

第二章提到java内存运行区域时包含了程序计数器、虚拟机栈、本地方法栈、java堆和方法区,占用内存的主要是堆和栈,其中栈主要是与运行线程相关,所以线程运行结束,栈也随着消亡。hotspot虚拟机采用了永久代(GC的一种分代概念)去实现了方法区,所以方法区的GC效率很低。因此对于内存分配时的优化就集中在java堆内存中。

垃圾收集自然要涉及到垃圾的认定,java中对象如果不可能再被任何路径使用,则为对象已死,也即为要被回收的垃圾。有点像寻梦环游记中的设定,如果被所有人遗忘了,那就是真正的死去了。有两种方法判定对象是否存活,即引用计数算法和可达性分析算法。引用计数算法就是给对象增加一个引用计数器,每有一个地方引用它,计数器值加一,引用失效时则减一,但是主流java虚拟机并没有采用这种方法,原因是存在对象互相引用的情况,A引用B,B引用A,但是A、B没被任何别的地方引用,采用引用计数算法无法回收A和B。可达性分析算法是通过一系列名为“GC Roots”的对象作为起始点向下搜索,经过引用链(Reference Chain)的遍历到达所有对象,未能到达的对象视为对象不可用也即判定为死亡,类似图论中图的遍历。java中的虚拟机栈引用对象、方法区中类静态属性引用对象、常量引用对象、本地方法栈引用对象均可作为GC Roots对象。

对象存活的判定算法中涉及到引用的概念,reference类型数据中存储的数值是另外一块内存的其实地址即为存在引用。jdk1.2之后对引用划分为强引用(strong reference)、软引用(soft reference)、弱引用(soft reference)、虚引用(phantom reference),用于满足一些内存足够则保留,不足则回收的需求。强引用既是代码指定了对象之间关系的引用,类似“Object obj=new Object()”,软引用是指有用但非必需,内存不足时将其回收,弱引用是指关联对象只能生存到下次垃圾收集之前,GC时会直接回收弱引用,它只是建立了一种对象的可达性条件,使弱引用对象可以被get到,虚引用完全不影响任何对象生存空间,也不能建立可达性条件,只可以达到在虚引用对象被GC回收时收到系统通知的目的。

在对象通过可达性算法条件判定为死亡后,只是达到了一个死缓的效果,对象可以在finalize()方法中有脱离死亡命运的最后一次机会,它可以在finalize方法中与引用链上的对象建立关联关系进而脱离死亡命运,但是finalize方法只会被执行一次,第二次对象判定为死亡时会直接被回收掉。

方法区(即hotspot中的永久代)垃圾收集主要回收废弃常量和无用类。废弃常量就是没有被任何地方引用的变量。无用类需满足1.所有该类的实例已被回收。2.加载该类的classloader已被回收。3.该方法对应的java.object.Class对象没有在任何地方被引用。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!