何时以及如何在Java中收集类垃圾?

我在本主题中询问了有关Java中垃圾收集的问题 。 但我得到的答案,给了我另一个问题。

有人提到垃圾收集器也可以收集类。 这是真的?

如果确实如此,这是如何工作的?

当没有引用它时,Java中的类可以被垃圾收集。 在大多数简单的设置中,这种情况永远不会发生,但在某些情况下可能会发生。

有很多方法可以使类可以访问,从而阻止它符合GC的条件:

  • 该类的对象仍然可以访问。
  • 表示类的Class对象仍然可以访问
  • 加载类的ClassLoader仍然可以访问
  • ClassLoader加载的其他类仍然可以访问

当这些都不成立时, ClassLoader及其加载的所有类都符合GC的条件。

这是一个应该演示行为的构造示例(充满了不良做法!):

在目录(而不是包!) x创建字节码文件GCTester.class 。 它的源代码是:

 public class GCTester { public static final GCTester INSTANCE=new GCTester(); private GCTester() { System.out.println(this + " created"); } public void finalize() { System.out.println(this + " finalized"); } } 

然后在x的父目录中创建一个类TestMe

 import java.io.File; import java.net.URL; import java.net.URLClassLoader; import java.lang.reflect.Field; public class TestMe { public static void main(String[] args) throws Exception { System.out.println("in main"); testGetObject(); System.out.println("Second gc() call (in main)"); System.gc(); Thread.sleep(1000); System.out.println("End of main"); } public static void testGetObject() throws Exception { System.out.println("Creating ClassLoader"); ClassLoader cl = new URLClassLoader(new URL[] {new File("./x").toURI().toURL()}); System.out.println("Loading Class"); Class clazz = cl.loadClass("GCTester"); System.out.println("Getting static field"); Field field = clazz.getField("INSTANCE"); System.out.println("Reading static value"); Object object = field.get(null); System.out.println("Got value: " + object); System.out.println("First gc() call"); System.gc(); Thread.sleep(1000); } } 

运行TestMe将生成此(或类似)输出:

在主要
创建ClassLoader
装载class级
获得静态领域
读取静态值
 GCTester @ 1feed786创建
得到的价值:GCTester @ 1feed786
第一次gc()调用
第二次gc()调用(在main中)
 GCTester @ 1feed786敲定
主要结束

在倒数第二行,我们看到GCTester实例已经完成,这只能意味着类(和ClassLoader )符合垃圾回收的条件。