【发布时间】:2010-10-27 22:03:19
【问题描述】:
调用 System.gc() 或 finalize() 方法时,内部 (JVM) 发生了什么?
这真的是收集垃圾还是降低性能?
【问题讨论】:
-
请记住,GC 行为依赖于实现,因此它会在 VM 之间发生变化。
标签: java garbage-collection jvm finalize
调用 System.gc() 或 finalize() 方法时,内部 (JVM) 发生了什么?
这真的是收集垃圾还是降低性能?
【问题讨论】:
标签: java garbage-collection jvm finalize
是 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 方法都会被调用。
【讨论】:
System.gc 并不能保证它会立即调用垃圾收集器来释放内存。只是建议!!!
finalize() 是一种在对象准备好进行垃圾回收之前执行最后一段代码的方法(当对象没有强引用时)。
那么应该什么时候使用呢? 仅在目前的两种情况下:
除了以上两种情况,千万不要使用它。明白为什么?我们需要了解对象的功能和生命周期。
简介:有一个单独的守护线程称为终结器线程,负责调用 finalize() 方法。终结队列是放置准备调用 finalize() 方法的对象的队列。
当一个对象准备好进行垃圾收集时,垃圾收集器线程会检查该特定对象是否具有来自 (1) 中提到的表的 finalize()。
2a) 如果没有,则将其发送给垃圾回收。
2b) 它是有的,然后它被添加到终结队列中。它会从表 (1) 中删除对象的条目。
终结器线程不断轮询队列。对于队列中的每个对象,都会调用其 finalize() 方法。在从 (2) 调用 finalize() 循环后,再次重复。如果此对象仍然没有强引用,则发送 GC。如果 然后总是调用 (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() 它将关闭必要的资源或用于最终日志等。 the complete post on it。我希望这可以清除。
【讨论】:
System.gc() 清理内存,并使用 finalize() 删除单个对象。
【讨论】:
通过调用System.gc(),垃圾收集器运行,正如其名。此时,当对象真正被移除时,会在这些对象消失之前调用finalize()。
最后一个问题中不应包含“or”。这是垃圾收集和降低性能。
通常你根本不应该关心gc,因为它对你来说真的很好。有一些使用场景,你想在某个时间点摆脱很多对象;那么是可行的。
【讨论】:
调用System.gc() 时发生的确切情况取决于JVM。 JVM 将此调用视为建议,它可能是运行垃圾收集器的好时机,所以不要依赖它。
当 JVM 确定不再有对该对象的可访问引用时,垃圾收集器对该对象运行对象的 finalize() 方法。你不应该在你的代码中调用它。请记住,finalize() 不会在您的程序丢失该最终引用时调用,而是在将来运行垃圾收集器时调用,因此不要依赖它发生在特定的时间点(或根本没有)。
【讨论】:
如果您想了解垃圾回收的内部机制,您应该阅读来自 Sun 的 Hotspot Memory Management Whitepaper。
【讨论】: