Я был заинтригован answer подобным вопросом. Я считаю, что это неверно. Поэтому я создал тестовый код. Мой вопрос заключается в том, что этот код доказывает/опровергает/отрицает гипотезу о том, что полезно аннулировать переменные-члены в методах слежения? Я тестировал его с помощью JUnit4.8.1.Действительно ли необходимо аннулировать объекты в методах JUnit teardown?
JUnit создает новый экземпляр тестового класса для каждого из 4 тестов. Каждый экземпляр содержит Object obj. Этот obj также вставлен как ключ статического WeakHashMap. Если и когда JUnit выпускает свои ссылки на тестовый экземпляр, связанное с ним значение obj будет слабо ссылаться и, следовательно, иметь право на gc. Тест пытается заставить gc. Размер WeakHashMap скажет мне, являются ли objs gc'ed. Некоторые тесты аннулировали переменную 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 был сведен и в Test1 это дс «ред. Но test1 obj не был аннулирован, и он получил gc'ed в Test2. Это говорит о том, что обнуление объектов не требуется.
Это лучший ответ. Нулеумирование необходимо (чтобы избежать утечки памяти) в JUnit 3.x. Если вы используете JUnit4.x, а нумерация по умолчанию для бегуна не требуется. Если вы используете пользовательский бегун, вам может потребоваться аннулировать. – emory