问题描述
我在这个主题中询问了有关Java垃圾收集的问题。
但是我得到的答案,给了我另一个问题。
有人提到类可以被垃圾回收器收集。
这是真的吗?
如果是真的,这是如何工作的?
Java中的类可以在没有引用它时进行垃圾回收。在大多数简单的设置中,这种情况不会发生,但在某些情况下可能会发生。
有很多方法可以使类可达,
- 该类别的物件仍然可以存取。
-
- 加载类的
ClassLoader
>
-
ClassLoader
载入的其他类别仍然可以访问
当没有是真的,那么 ClassLoader
和它加载的所有类都适用于GC。
这里是一个构建的示例(完整的错误的做法!),应该展示行为:
创建一个字节码文件 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);
}
}
然后创建一个类 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(获取静态字段);
字段字段= clazz.getField(INSTANCE);
System.out.println(读取静态值);
Object object = field.get(null);
System.out.println(Got value:+ object);
System.out.println(First gc()call);
System.gc();
Thread.sleep(1000)
}
}
运行 TestMe
将产生这个(或类似的)输出:
在main
创建ClassLoader
加载类
获取静态字段
读取静态值
GCTester @ 1feed786 created
值:GCTester @ 1feed786
第一个gc()调用
第二个gc()调用in main)
GCTester @ 1feed786 finalized
end of main
在第二行到最后一行,我们看到 GCTester
实例已完成,这只能意味着类(和 ClassLoader
)有资格进行垃圾回收。 p>
I asked a question about Garbage Collection in Java in this topic. But the answer I got, gave me another question.
Someone mentioned that classes can be collected by the garbage collector too. Is this true?
And if it is true, how does this work?
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.
There are many ways to make a class reachable and thus prevent it from being eligible for GC:
- objects of that class are still reachable.
- the
Class
object representing the class is still reachable - the
ClassLoader
that loaded the class is still reachable - other classes loaded by the
ClassLoader
are still reachable
When none of those are true, then the ClassLoader
and all classes it loaded are eligible for GC.
Here's a constructed example (full of bad practices!) that should demonstrate the behaviour:
Create a bytecode file GCTester.class
in a directory (not package!) x
. It's source code is:
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 TestMe
in the parent directory of 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 TestMe
will produce this (or similar) output:
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 GCTester
instance is finalized, which can only mean that the class (and ClassLoader
) are eligible for garbage collection.
这篇关于什么时候和如何在Java中收集类的垃圾?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!