我被一个类似的问题的答案吸引了。 我认为那个答案是错误的。 因此,我创建了一些测试代码。我的问题是,这段代码是否证明/反驳/不确定在tearDown方法中将成员变量赋值为空是有用的假设? 我使用JUnit4.8.1进行了测试。
JUnit为每个测试创建测试类的新实例。 每个实例都包含一个Object obj。 这个obj也作为静态WeakHashMap的键插入其中。 如果JUnit释放对测试实例的引用,则相关联的obj值将变得弱引用并因此适合垃圾回收。 测试试图强制进行垃圾回收。 WeakHashMap的大小将告诉我objs是否已被垃圾回收。 一些测试将obj变量赋值为空,而另一些则没有。
import org . junit . Before ;
import org . junit . After ;
import org . junit . Test ;
import java . util . ArrayList ;
import java . util . WeakHashMap ;
import java . util . concurrent . atomic . AtomicInteger ;
import static org . junit . Assert . * ;
public class Memory
{
static AtomicInteger idx = new AtomicInteger ( 0 ) ;
static WeakHashMap < Object , Object > map = new WeakHashMap < Object , Object > ( ) ;
int id ;
Object obj ;
boolean nullify ;
public Memory ( )
{
super ( ) ;
}
@ Before
public void before ( )
{
id = idx . getAndIncrement ( ) ;
obj = new Object ( ) ;
map . put ( obj , new Object ( ) ) ;
System . out . println ( "<BEFORE TEST " + id + ">" ) ;
}
void test ( boolean n )
{
nullify = n ;
int before = map . size ( ) ;
gc ( ) ;
int after = map . size ( ) ;
System . out . println ( "BEFORE=" + before + "\tAFTER=" + after ) ;
}
@ Test
public void test0 ( )
{
test ( true ) ;
}
@ Test
public void test1 ( )
{
test ( false ) ;
}
@ Test
public void test2 ( )
{
test ( true ) ;
}
@ Test
public void test3 ( )
{
test ( false ) ;
}
@ After
public void after ( )
{
if ( nullify )
{
System . out . println ( "Nullifying obj" ) ;
obj = null ;
}
System . out . println ( "<AFTER TEST " + id + ">" ) ;
}
/**
* Try to force a gc when one is not really needed.
**/
void gc ( )
{
ArrayList < Object > waste = new ArrayList < Object > ( ) ;
System . gc ( ) ; // only a suggestion but I'll try to force it
list :
while ( true ) // try to force a gc
{
try
{
waste . add ( new Object ( ) ) ;
}
catch ( OutOfMemoryError cause )
{
// gc forced? should have been
waste = null ;
break list ;
}
}
System . gc ( ) ; // only a suggestion but I tried to force it
}
}
我使用命令行界面运行了该代码(利用-Xmx128k选项来增加垃圾收集),并得到了以下结果
.<BEFORE TEST 0>
BEFORE=1 AFTER=1
Nullifying obj
<AFTER TEST 0>
.<BEFORE TEST 1>
BEFORE=2 AFTER=1
<AFTER TEST 1>
.<BEFORE TEST 2>
BEFORE=2 AFTER=1
Nullifying obj
<AFTER TEST 2>
.<BEFORE TEST 3>
BEFORE=2 AFTER=1
<AFTER TEST 3>
Test0对象被设置为null并在Test1中被垃圾回收。但是Test1对象没有被设置为null,却在Test2中被垃圾回收。这表明将对象设置为null并不是必需的。