我目前遇到的问题是我的类中的对象没有调用finalize()
方法,尽管只将ConcurrentHashMap
存储为值,而对象的UUID
为地图的关键。
这是我创建的一个示例(它不是我实际项目中使用的示例,但此示例也没有调用对象的finalize()
方法。
TestMain.class //处理HashMap的主类
public class TestMain {
public static ConcurrentHashMap<String, WeakReference<Test>> map = new ConcurrentHashMap<String, WeakReference<Test>>();
public static void main(String args[]) {
map.put("Key1", new WeakReference<Test>(new Test("test 1", 2))); //This "Test" Object shouldn't be accessible anywhere besides the HashMap anymore, and therefore I want it to be "finalized" by the garbage collector.
System.out.println("DONE");
}
}
Test.class //对象类
public class Test {
public String string;
public int intt;
public Test(String string, int intt) {
this.string = string;
this.intt = intt;
}
@Override
protected void finalize() throws Throwable {
System.out.println("FINALIZED TEST CLASS: " + string);
super.finalize();
}
}
当运行主方法时,所有打印的内容都是“DONE”,当我预期“FINALIZED TEST CLASS:Test 1”也会在此之前打印。我的代码有问题,还是我误解了finalize()
的工作原理?
另外,我希望这可以解释,因为我需要使用finalize()
方法从“地图”Map
和内存中删除对象,因为会有数百个在项目的运行持续时间内生成的对象,所以我希望不再使用不再使用的对象为更多新对象腾出空间。
while(true){}
循环终止并等待几分钟,但仍然没有看到对象的消息被“最终确定”。
非常感谢任何帮助,谢谢。
答案 0 :(得分:3)
最可能的解释是GC从未运行过。
如果GC未运行,则不会对对象进行垃圾回收。
如果未收集对象,则无法最终确定。
尝试通过添加一个简单的while(true){}循环来让我的程序不终止,并等待几分钟,
等待GC无济于事。通常它仅在&gt;&gt;需要&lt;&lt;跑;即当其中一个堆空间超过饱满度时。
您可以通过调用System.gc()
强制GC运行...但这是 BAD PRACTICE 。它会使您的应用程序效率低下且无响应。
尝试在必须及时完成的终结器中做任何事情也是不明智的。您应该设计代码,以便:
为什么呢?因为你几乎无法控制对象的最终确定时间......如果你没有调用System.gc()
那就根本没有控制......你不应该这样做;见上文。
在实践中,终结器是Java的一个特性,如果有的话应该很少使用。唯一有效的用例涉及释放与应用程序尚未整理的资源对象关联的外部资源。即便如此,应用程序最好使用“try with resources”(或finally
块)来明确清理资源。
答案 1 :(得分:1)
正如评论中正确提到的那样,无法保证调用finalize方法。
Java编程语言不保证哪个线程会 为任何给定对象调用finalize方法。这是有保证的, 但是,调用finalize的线程不会持有任何 调用finalize时,用户可见的同步锁定。如果 finalize方法抛出未捕获的异常,例外是 忽略并终止该对象的终结。
现在回过头来关注在不再可访问这些对象之后手动处理这些对象,您无需处理它,Java垃圾收集器会使用它的自动内存管理来处理它。如果您想加速垃圾收集,请阅读G1垃圾收集器。