什么是类的卸载?它是如何工作的?代码举例讲解

类的卸载是Java虚拟机将类的Class对象及其对应的二进制数据从方法区中移除的过程。

类的卸载主要发生在两个时机:

  1. 垃圾收集时:如果类的Class对象没有任何引用指向,则会被垃圾收集器回收,导致该类被卸载。
  2. 程序退出时:Java虚拟机退出时会卸载所有的类。

类的卸载过程如下:

  1. 类的Class对象没有任何引用时,会被标记为不可达的,可以被垃圾收集。
  2. 垃圾收集器回收不可达的Class对象。
  3. 虚拟机检查该Class对象是否还属于任何其它对象的引用路径。如果没有,则可以将其卸载。
  4. 虚拟机执行类的 unload 方法,将其类信息,常量池等从方法区中清除。
  5. 类的字节码文件仍然保留在磁盘中,可以在以后重新加载。

需要注意的是,类的卸载不会影响该类的已实例化对象,这些对象依然可以正常使用。只不过,随着这些对象的逐渐消失,该类的影响也会逐渐减小。

来看一个简单例子:

public class UnloadingDemo {
    public static void main(String[] args) {
        Son s = new Son();
        s = null;     // Son类的引用设置为null

        // 手动触发垃圾收集
        System.gc(); 

        // Son类是否已经被卸载
        System.out.println(Son.class);  
    }
}

class Son {}

在上述程序中:

  1. 新创建Son类的实例s,Son类会被加载到内存中。
  2. s引用设置为null,Son类的Class对象变为不可达。
  3. 执行System.gc()后,Son类的Class对象会被垃圾收集器回收。
  4. 由于Son类没有其它引用,会被虚拟机卸载,Class对象也会被清除。
  5. 所以打印Son.class会抛出NoClassDefFoundError错误。