【发布时间】:2011-01-26 20:33:59
【问题描述】:
【问题讨论】:
-
您可能会发现这个主题很有帮助:stackoverflow.com/questions/453023/…
-
这个也是:“Java 类加载器何时以及如何标记为垃圾收集?” stackoverflow.com/questions/2344964/…
标签: java garbage-collection class
【问题讨论】:
标签: java garbage-collection class
Java 中的类可以在没有任何引用的情况下被垃圾回收。在大多数简单的设置中,这永远不会发生,但在某些情况下可能会发生。
有很多方法可以使类可访问,从而阻止它符合 GC 条件:
Class 对象仍然可以访问ClassLoader仍然可以访问ClassLoader 加载的其他类仍然可以访问当 none 为真时,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 将产生这个(或类似的)输出:
在倒数第二行中,我们看到GCTester 实例已完成,这只能意味着该类(和ClassLoader)有资格进行垃圾回收。
【讨论】:
Class 有资格获得 GC。现在,即使我们已经清除了 4 个障碍,系统是否仍有可能没有收集到Class?基本上,我要问的是 JLS 是说 JVM 应该 释放未引用的Class 还是说 JVM 必须-最终发布一个未引用的Class?