我正在尝试编写一个Java单元测试,用于测试对对象的终结器调用的效果。
为了确保终结器被调用,我使用了在stackoverflow的其他地方看到的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);
}
}发布于 2012-03-03 05:35:23
在单元测试中添加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()是一种建议,如果系统愿意的话,它可以忽略您。作为补充,我还确保没有任何东西是静态的,不确定这是否重要。
发布于 2012-03-03 04:51:56
您对System.gc的调用只是一个建议,而不是命令。
没有明确保证任何终结器都会被调用。
在您的例子中,终结器可能会在VM退出时调用。
https://stackoverflow.com/questions/9540114
复制相似问题