当Sample类被加载、链接和初始化后,他的生命周期就开始了。当代表Sample类的Class对象不再被引用,即不可触及时,堆上的Class对象就会被回收结束生命周期,Sample类在方法区内的数据也会被卸载,从而结束Sample类的生命周期。一个类何时结束生命周期,取决于代表它的Class对象何时结束生命周期。
下图为针对Sample的可达性分析引用图
根据可达性分析算法分析如果要让Sample类卸载即让GCROOT和堆里的Sample.class实例没有引用关系,由于③、⑤不可能断,所以只能断掉引用①、②、③,此时Sample类和方法区里的Sample元数据将一起被回收,卸载。(MyClassLoader类不会被回收,因为MyClassLoader.class的引用还被系统类加载器持有,最多堆里的MyClassLoader实例被回收)
方法区的垃圾收集主要回收两部分内容:常量池中废弃的常量和不在使用的类型(instanceKlass)。
Hotspot虚拟机对常量池的回收策略是很明确的,只要常量池中的常量没有被任何地方引用,就可以被回收。
判定一个常量是否“废弃”还是相当简单的,而要判定一个类型是否数据“不再被使用的类”的条件就比较苛刻了。同时需要满足下面三个条件:
再加上方法区只有在full_gc的时候才会触发,本身频率就很低,所以一个已加载的类型被卸载的几率很小,被卸载的时间也不确定。所以我们平时开发代码时,不应该对虚拟机的类型卸载做任何假设的前提下,来实现系统中的特定功能。