什么时候和如何在Java中收集类的垃圾? [英] When and how are classes garbage collected in Java?

查看:134
本文介绍了什么时候和如何在Java中收集类的垃圾?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在这个主题中询问了有关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中收集类的垃圾?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆