在这里,我们借用黑马程序员的课程截图以便于阐述问题:
在栈和堆内存都释放之后,方法区的Class元数据会不会卸载以及什么时候卸载?
在解决这个问题之前,我们要先了解1个概念----类加载器
类加载器是负责读取 .class 字节码文件,把它转换成 JVM 内部 Class 元数据,放到方法区的工具。所有 Java 类,都必须靠类加载器加载后才能使用。每一个被加载的类,都会记录是谁把它加载进来的(该类所使用的类加载器)。
(类加载器本身也是一个Java对象,Bootstrap启动类加载器除外,感兴趣可以自行了解,这里不影响问题解决)
------------------------------------------------------------------------------------------------------------------
类加载器可以分为两种,一种是系统加载器,一种是自定义加载器
系统类加载器(AppClassLoader)是JDK内置的,原生提供,该加载器对象被JVM强引用,是不可被GC回收的,想要卸载其加载出来的Class元数据只能等JVM进程退出之后才可以,我们无法对其修改
自定义类加载器是由我们自己继承ClassLoader后手写实现的,这种对象是普通对象,可以被GC回收,而其加载出来的Class元数据也可以类卸载,这种加载器我们可以修改字节码读取逻辑
类卸载的三个条件:
三个条件全部达成,就算JVM还没有关闭,仍然可以把方法区里这个Class元数据卸载回收,释放内存。
总结:我们现在知道了,如果当前Class元数据由系统类加载器所加载就需要等JVM进程退出之后才可以进行类卸载,如果是自定义类加载器就需要满足我们刚才所说的三个条件就可以直接类卸载了.
- 加载该类的自定义类加载器对象自身被GC回收了
- 该类的所有实例对象全部被GC回收(堆里不可以再有当前类的对象)
- 没有地方引用该Class对象