为啥在这个单元测试中没有调用 finalize 函数?
Posted
技术标签:
【中文标题】为啥在这个单元测试中没有调用 finalize 函数?【英文标题】:Why does the finalize function not get called in this unit test?为什么在这个单元测试中没有调用 finalize 函数? 【发布时间】:2012-03-02 20:45:51 【问题描述】:我正在尝试编写一个 Java 单元测试来测试调用终结器对对象的影响。
为了确保调用终结器,我使用了我在 *** 其他地方看到的 WeakReference 方法。
我的问题是,在这个测试中,TestFinalizer 的 finalize 方法永远不会被调用,即使 WeakReference 仅在一次迭代后就变为 null:
public class FinalizerTest
private static class TestFinalizer
public static class Callback
public int NumFinalize = 0;
public void finalized()
NumFinalize++;
private Callback callback;
public TestFinalizer(Callback callback)
this.callback = callback;
@Override
public void finalize() throws Throwable
callback.finalized();
super.finalize();
@Test
public void testForceFinalizer()
TestFinalizer.Callback callback = new TestFinalizer.Callback();
TestFinalizer testFinalizer = new TestFinalizer(callback);
// Try to force finalizer to be called
WeakReference<Object> ref = new WeakReference<Object>(testFinalizer);
testFinalizer = null;
int maxTries = 10000, i=0;
while (ref.get() != null && i<maxTries)
++i;
System.gc();
if ( ref.get() != null )
fail("testFinalizer didn't get cleaned up within maxTries");
// Last line passes, next fails!
assertEquals("Should be exactly one call to finalizer", 1, callback.NumFinalize);
【问题讨论】:
【参考方案1】:您致电System.gc
只是一个建议,而不是命令。
没有明确保证会调用任何终结器。
在您的情况下,可能会在 VM 退出时调用终结器。
【讨论】:
【参考方案2】:在单元测试中添加 Thread.sleep(3000) 解决了我机器上的这个问题:
@Test
public void testForceFinalizer() throws InterruptedException
FinalizerTest.TestFinalizer f = new FinalizerTest.TestFinalizer(null);
FinalizerTest.TestFinalizer.Callback callback = f.new Callback();
TestFinalizer testFinalizer = new TestFinalizer(callback); // Try to
// force
// finalizer
// to be
// called
WeakReference<Object> ref = new WeakReference<Object>(testFinalizer);
testFinalizer = null;
int maxTries = 10000, i = 0;
while (ref.get() != null && i < maxTries)
++i;
System.gc();
if (ref.get() != null)
fail("testFinalizer didn't get cleaned up within maxTries"); // Last
// line
// passes,
// next
// fails!
System.out.println("Value: " + callback.NumFinalize);
Thread.sleep(3000);
assertEquals("Should be exactly one call to finalizer", 1,
callback.NumFinalize);
System.out.println("Value after: " + callback.NumFinalize);
这是在 assertEquals
调用之前执行的。正如其他人所说,调用 System.gc() 是一个建议,如果系统选择,系统可以忽略你。另外,我还确保没有什么是静态的,不确定这是否重要。
【讨论】:
是的,Thread.sleep(3000);在那里也为我修好了。我想这是因为即使弱 ref 已经被清空,终结器线程仍然需要做它的事情......【参考方案3】:调用 gc 方法表明 Java 虚拟机花费精力回收未使用的对象,以使它们当前占用的内存可用于快速重用。
System.gc()
不会触发垃圾回收。
如果您在 while 循环中添加 (没有帮助,刚刚测试)Thread.sleep(xxx)
并等待一段时间,您可能会很幸运地看到终结器被调用。
【讨论】:
以上是关于为啥在这个单元测试中没有调用 finalize 函数?的主要内容,如果未能解决你的问题,请参考以下文章
python中unittest 单元测试调用没有调用到测试用例,新手求指点
为啥在 Quick 的单元测试中多次调用 before- 和 afterEach 块?