5

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

这真的是收集垃圾还是降低性能?

4

6 回答 6

8

调用System.gc()时发生的确切情况取决于 JVM。JVM 将此调用视为建议它可能是运行垃圾收集器的好时机,因此不要依赖它。

当 JVM 确定不再有对该对象的可访问引用时,垃圾收集器对该对象运行对象的finalize()方法。你不应该在你的代码中调用它。请记住,finalize()不会在您的程序丢失该最终引用时被调用,而是在垃圾收集器运行的未来时间被调用,因此不要依赖它在特定时间点(或在全部)。

于 2009-05-21T13:51:36.217 回答
3

如果您想了解垃圾收集的内部原理,您应该阅读Sun 的热点内存管理白皮书。

于 2009-05-21T12:32:27.143 回答
1

System.gc()顾名思义,通过调用垃圾收集器运行。此时,当对象真正被删除时,finalize()会在这些对象消失之前调用它们。

最后一个问题不应该有“ or”。这是垃圾收集降低性能。

通常你根本不应该关心gc,因为它对你来说真的很好。有一些使用场景,你想在某个时间点摆脱很多对象;那么是可行的。

于 2009-05-21T12:24:21.387 回答
0

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

于 2012-04-17T07:01:18.723 回答
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 方法都会被调用。

于 2014-04-09T07:07:46.887 回答
0

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

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

  1. 作为安全措施,以确保关闭某些服务或进行某些所需的最终更改。例如 InputStream 类使用它来关闭 i/o 流。例如,您创建了一个 BufferedInputStream 实例。使用后手动关闭()它。但是因为人们可能忘记这样做,所以 finalize() 充当了 close() 流的安全网。
  2. 在使用 Native 的时候。因为垃圾收集器无法控制原生对象,所以可以使用 finalize() 作为回收它的一种手段。

除上述两种情况外永远不要使用它。明白为什么?我们需要了解对象的功能和生命周期。

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

  1. 创建对象时,JVM 会检查该对象是否具有 finalize() 方法。如果有,那么它在内部说明这个特定对象有 finalize() 方法。

当一个对象准备好进行垃圾收集时,垃圾收集器线程检查该特定对象是否具有来自 (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,否则所有这些对象都不会被释放。如果所有对象都是重量级对象,则可能会出现短缺。

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

如果在 finalize() 中抛出异常,则将其忽略。

您不知道何时调用 finalize(),因为您无法控制何时调用 GC。有时可能会发生您在 finalize() 中打印值但从未显示输出的情况,因为您的程序可能在调用 finalize() 时已经终止。

因此避免使用它。而是创建一个方法说 dispose() ,它将关闭必要的资源或最终日志等。 完整的帖子。我希望这能清除。

于 2011-10-18T08:40:05.830 回答