调用System.gc()或finalize()方法时内部发生了什么(JVM)?

时间:2009-05-21 12:21:07

标签: java garbage-collection jvm finalize

当System.gc()或finalize()方法被调用时,内部发生了什么(JVM)?

这真的会收集垃圾或降低性能吗?

6 个答案:

答案 0 :(得分:8)

当您调用System.gc()时,恰好会发生与JVM相关的事情。 JVM将此调用视为建议,它可能是运行垃圾收集器的好时机,因此不要依赖它。

当JVM确定对该对象没有更多可访问的引用时,垃圾收集器会在对象上运行对象的finalize()方法。你不应该在你的代码中调用它。请记住,在程序丢失最终引用时,finalize()是 not ,但是在将来运行垃圾收集器的时候,所以不要依赖于它发生在特定时间点(或根本)。

答案 1 :(得分:3)

如果您想了解垃圾收集内部,请阅读Sun的Hotspot Memory Management Whitepaper

答案 2 :(得分:1)

通过调用System.gc()运行垃圾收集器,如名称所示。此时,当真正删除对象时,会在这些对象消失之前调用finalize()

最后一个问题不应该包含“or”。垃圾收集降低了性能。

通常你根本不应该关心gc,因为它对你来说非常好。在某些使用场景中,您希望在某个时间点摆脱大量对象;那就可行了。

答案 3 :(得分:0)

finalize()是在对象准备好进行垃圾收集之前执行最后一位代码的方法(当对象没有强引用时)。

那么什么时候应该使用? 仅在目前的两种情况下:

  1. 作为确保某些服务关闭或某些服务的安全措施 期望的最终改变。例如,InputStream类使用它 关闭i / o流。那就是你做了一个 BufferedInputStream的实例。使用后手动一个是 假设关闭()它。但因为人们可以忘记这样做, finalize()act作为关闭()流的安全网。
  2. 虽然 使用Native的。因为垃圾收集器无法控制本机 对象,finalize()可以用作回收它的手段。
  3. 除上述两种情况外,从不使用它。要明白为什么?我们需要了解对象的功能和生命周期。

    简介:有一个单独的守护程序线程,称为终结器线程,负责调用finalize()方法。终结队列是一个队列,其中放置了准备被称为finalize()方法的对象。

    1. 创建Object时,JVM会检查对象是否具有finalize()方法。如果它有,那么它在内部注意到这个特定的对象有finalize()方法。
    2.   

      当一个对象准备好进行垃圾收集时,垃圾收集器线程会检查这个特定对象是否具有(1)中提到的表中的finalize()。

      • 2a)如果没有,则将其发送给垃圾收集。

        2b)它有,然后它被添加到终结队列。它从表(1)中删除了对象的条目。

      终结器线程继续轮询队列。对于队列中的每个对象,都会调用其finalize()方法。从(2)调用finalize()循环后再次重复。如果此对象仍然没有强引用,则发送给GC。如果     然后调用ALWAYS(2a),因为在(2b)

      中删除了条目
      Basically finalize() method is only called once.
      

      那么上述周期的问题是什么?

        

      从(1)开始。它在对象创建中花费了额外的时间。 Java中的内存分配比malloc / calloc等快5到10倍。在注意到表中的对象的过程中,所有获得的时间都丢失了。我曾经尝试过。在循环中创建100000个对象并测量程序在2种情况下终止所花费的时间:一个没有finalize(),第二个是finalize()。发现它快了20%。

           

      从(2b):记忆泄漏和饥饿。如果队列中的对象引用了大量内存资源,那么除非此对象已准备好用于GC,否则所有这些对象都不会被释放。如果所有对象都是重量级对象,那么可能会出现短缺。

           

      From(2b):因为finalize()只被调用一次,所以如果在finalize()中你有一个强烈的“this”对象引用。下次永远不会调用对象的finalie()因此会使对象处于不一致状态。

           

      如果在finalize()内部抛出异常,则忽略它。

      您不知道何时调用finalize(),因为您无法控制何时调用GC。有时可能会在finalize()中打印值,但输出永远不会显示,因为你的程序可能在调用finalize()时被终止。

      因此避免使用它。而是创建一个方法,例如dispose(),它将关闭必需资源或最终日志等。 the complete post on it。我希望这清楚。

答案 4 :(得分:0)

System.gc()清理内存,并使用finalize()来删除单个对象。

答案 5 :(得分:0)

是System.gc();如果需要,将触发finalize()方法。 公共类TestGarbageCollection {

public static void main(String[] args) {
    while (true) {
        TestClass s = new TestClass();
        s.display();
        System.gc();
    }
}

}

公共类TestClass {

public TestClass() {
    System.out.println("constructor");
}

public void display() {
    System.out.println("display");
}
@Override
public void finalize() {
    System.out.println("destructor");
}

}

这将触发finalize()方法。是否覆盖finalize或不终结本地类的方法或将调用Object的finalize。