文章目录
前言
语雀地址:https://www.yuque.com/yangxiaofei-vquku/wmp1zm/dmz2gd一、描述
当Sample类被加载、链接和初始化后,他的生命周期就开始了。当代表Sample类的Class对象不再被引用,即不可触及时,堆上的Class对象就会被回收结束生命周期,Sample类在方法区内的数据也会被卸载,从而结束Sample类的生命周期。一个类何时结束生命周期,取决于代表它的Class对象何时结束生命周期。
二、图例
下图为针对Sample的可达性分析引用图
根据可达性分析算法分析如果要让Sample类卸载即让GCROOT和堆里的Sample.class实例没有引用关系,由于③、⑤不可能断,所以只能断掉引用①、②、③,此时Sample类和方法区里的Sample元数据将一起被回收,卸载。(MyClassLoader类不会被回收,因为MyClassLoader.class的引用还被系统类加载器持有,最多堆里的MyClassLoader实例被回收)
三、方法区的垃圾回收
方法区的垃圾收集主要回收两部分内容:常量池中废弃的常量和不在使用的类型(instanceKlass)。
Hotspot虚拟机对常量池的回收策略是很明确的,只要常量池中的常量没有被任何地方引用,就可以被回收。
判定一个常量是否“废弃”还是相当简单的,而要判定一个类型是否数据“不再被使用的类”的条件就比较苛刻了。同时需要满足下面三个条件:
- 该类所以的实例都已经被回收,也就是java堆中不存在该类及其任何派生子类的实例。
- 加载该类的类加载器实例已经被回收,这个条件除非是经过精细设计的课替换类加载器的场景,如OSGi、JSP的重加载等,否则通常很难达成的。
- GCROOT没有任何引用可以访问到该类对应的java.lang.Class对象实例,无法在任何地方通过反射访问该类。
再加上方法区只有在full_gc的时候才会触发,本身频率就很低,所以一个已加载的类型被卸载的几率很小,被卸载的时间也不确定。所以我们平时开发代码时,不应该对虚拟机的类型卸载做任何假设的前提下,来实现系统中的特定功能。