When and how are classes garbage collected in Java?

后端 未结 1 1615
孤街浪徒
孤街浪徒 2020-11-29 03:48

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

相关标签:
1条回答
  • 2020-11-29 04:38

    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.

    0 讨论(0)
提交回复
热议问题