什么时候以及如何在 Java 中垃圾收集类?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2433261/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When and how are classes garbage collected in Java?
提问by JordyOnrust
I asked a question about Garbage Collection in Java in this topic. But the answer I got, gave me another question.
我在这个主题中问了一个关于 Java 中垃圾收集的问题。但是我得到的答案又给了我另一个问题。
Someone mentioned that classes can be collected by the garbage collector too. Is this true?
有人提到垃圾收集器也可以收集类。这是真的?
And if it is true, how does this work?
如果这是真的,这是如何工作的?
回答by Joachim Sauer
A class in Java can be garbage-collected when nothing references it. In most simple setups this never happens, but there are situations where it can occur.
Java 中的类可以在没有任何引用时被垃圾收集。在大多数简单的设置中,这种情况永远不会发生,但在某些情况下可能会发生。
There are many ways to make a class reachable and thus prevent it from being eligible for GC:
有很多方法可以使类可达,从而防止它符合 GC 的条件:
- objects of that class are still reachable.
- the
Classobject representing the class is still reachable - the
ClassLoaderthat loaded the class is still reachable - other classes loaded by the
ClassLoaderare still reachable
- 该类的对象仍然可以访问。
Class代表类的对象仍然可以访问- 在
ClassLoader这加载的类仍可达 - 加载的其他类
ClassLoader仍然可以访问
When noneof those are true, then the ClassLoaderand all classes it loaded are eligible for GC.
如果这些都不为真,那么ClassLoader它加载的类和所有类都有资格进行 GC。
Here's a constructed example (full of bad practices!) that should demonstrate the behaviour:
这是一个构建的示例(充满了不好的做法!),它应该展示这种行为:
Create a bytecode file GCTester.classin a directory (not package!) x. It's source code is:
GCTester.class在目录(不是包!)中创建一个字节码文件x。它的源代码是:
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");
}
}
Then create a class TestMein the parent directory of x:
然后TestMe在 的父目录中创建一个类x:
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);
}
}
Running TestMewill produce this (or similar) output:
运行TestMe将产生这个(或类似的)输出:
in main Creating ClassLoader Loading Class Getting static field Reading static value GCTester@1feed786 created Got value: GCTester@1feed786 First gc() call Second gc() call (in main) GCTester@1feed786 finalized End of main
In the second to last line we see that the GCTesterinstance is finalized, which can only mean that the class (and ClassLoader) are eligible for garbage collection.
在倒数第二行中,我们看到GCTester实例已完成,这只能意味着类(和ClassLoader)有资格进行垃圾回收。

