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

标签 java garbage-collection class

我在 this topic 中问了一个关于 Java 垃圾收集的问题。 . 但我得到的答案,给了我另一个问题。

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

如果这是真的,这是怎么回事?

最佳答案

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 将产生这个(或类似的)输出:

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

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

关于java - Java 中何时以及如何收集类垃圾?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2433261/

相关文章:

java - 通过 ID 获取 Spring 事务并检查状态

javascript - 动态创建 map 时防止Java Nashorn过度占用内存

java - EMF eclipse : enumeration with custom fields (properties)

java - 如何使用 Spring 将数据传递给方法

java - 以编程方式捕获 Full GC 计数

java - 并行压缩收集器算法

javascript - 将 React 组件拆分为单独的文件

java - 如何从两个不同的循环将数据获取到构造函数中

c# - 要使用只读属性还是方法?

java - 将指向该对象的所有内容设置为 null