我需要知道什么时候在JVM中调用finalize()方法。我创建了一个测试类,当finalize()方法被重写时写入文件。它没有被执行。有人能告诉我为什么它不能执行吗?
当前回答
在最近与终结器方法搏斗之后(为了在测试期间处理连接池),我不得不说终结器缺少很多东西。使用VisualVM来观察以及使用弱引用来跟踪实际的交互,我发现以下事情在Java 8环境中是正确的(Oracle JDK, Ubuntu 15):
Finalize is not called immediately the Finalizer (GC part) individually owns the reference elusively The default Garbage Collector pools unreachable objects Finalize is called in bulk pointing to an implementation detail that there is a certain phase the garbage collector frees the resources. Calling System.gc() often does not result in objects being finalized more often, it just results in the Finalizer getting aware of an unreachable object more rapidly Creating a thread dump almost always result in triggering the finalizer due to high heap overhead during performing the heap dump or some other internal mechanism Finalization seams to be bound by either memory requirements (free up more memory) or by the list of objects being marked for finalization growing of a certain internal limit. So if you have a lot of objects getting finalized the finalization phase will be triggered more often and earlier when compared with only a few There were circumstances a System.gc() triggered a finalize directly but only if the reference was a local and short living. This might be generation related.
最后认为
最后确定方法是不可靠的,但只能用于一件事。您可以确保在垃圾收集之前关闭或释放对象,从而在正确处理涉及生命结束操作的更复杂生命周期的对象时实现故障安全。这是我能想到的一个值得我们去推翻它的原因。
其他回答
Finalize将打印出类创建的计数。
protected void finalize() throws Throwable {
System.out.println("Run F" );
if ( checkedOut)
System.out.println("Error: Checked out");
System.out.println("Class Create Count: " + classCreate);
}
main
while ( true) {
Book novel=new Book(true);
//System.out.println(novel.checkedOut);
//Runtime.getRuntime().runFinalization();
novel.checkIn();
new Book(true);
//System.runFinalization();
System.gc();
如你所见。下面的输出显示了类计数为36时第一次执行的gc。
C:\javaCode\firstClass>java TerminationCondition
Run F
Error: Checked out
Class Create Count: 36
Run F
Error: Checked out
Class Create Count: 48
Run F
一般来说,最好不要依赖finalize()来做任何清理等。
根据Javadoc(值得一读),它是:
当垃圾回收确定对象不再有引用时,由垃圾回收器在对象上调用。
正如Joachim指出的,如果对象总是可访问的,那么在程序的生命周期中,这可能永远不会发生。
此外,垃圾收集器不保证在任何特定时间运行。一般来说,我想说的是finalize()可能不是最好的方法,除非有特定的事情需要它。
最终确定方法是不保证的。当对象符合GC条件时调用此方法。在许多情况下,对象可能不会被垃圾收集。
类,在其中重写finalize方法
public class TestClass {
public TestClass() {
System.out.println("constructor");
}
public void display() {
System.out.println("display");
}
@Override
public void finalize() {
System.out.println("destructor");
}
}
finalize方法被调用的几率
public class TestGarbageCollection {
public static void main(String[] args) {
while (true) {
TestClass s = new TestClass();
s.display();
System.gc();
}
}
}
当内存被转储对象重载时,gc将调用finalize方法
运行并查看控制台,在那里你不会发现finalize方法被频繁调用,当内存超载时,finalize方法将被调用。
Finalize()在垃圾收集之前被调用。当对象超出作用域时,不调用它。这意味着您无法知道finalize()何时甚至是否会执行。
例子:
如果你的程序在垃圾回收发生之前结束,finalize()将不会执行。因此,它应该被用作备份过程,以确保其他资源的正确处理,或用于特殊用途的应用程序,而不是作为您的程序在其正常运行中使用的手段。
推荐文章
- 指定的子节点已经有一个父节点。你必须先在子对象的父对象上调用removeView() (Android)
- 对于一个布尔字段,它的getter/setter的命名约定是什么?
- 如何获得当前屏幕方向?
- 如何在Android中渲染PDF文件
- 如何计算一个元素在列表中出现的次数
- c++中类似于java的instanceof
- 我如何解决错误“minCompileSdk(31)指定在一个依赖的AAR元数据”在本机Java或Kotlin?
- 如何POST表单数据与Spring RestTemplate?
- Mockito中检测到未完成的存根
- 我应该如何复制字符串在Java?
- “while(true)”循环有那么糟糕吗?
- 这个方法签名中的省略号(…)是干什么用的?
- Java:如何测试调用System.exit()的方法?
- 带有返回类型的Java方法在没有返回语句的情况下编译
- Java“此语言级别不支持lambda表达式”