testng: Memory leak (TestNG seems to keep all test object in memory)
TestNG Version
6.9.10
Expected behavior
After completing a test, we expect test object to be garbage collected.
Actual behavior
Test objects are not finalized / garbage collected => which leads to an out of memory problem when running a large test suite
Is the issue reproductible on runner?
- Shell
- Maven
- Gradle
- Ant
- Eclipse
- IntelliJ
- NetBeans
Test case sample
Please find below a standalone main class reproducing this problem. It shows that test objects are not garbage collected / finalized
package test;
import org.testng.TestNG;
import org.testng.annotations.Test;
/**
* This class reproduces a memory leak problem when running TestNG tests.
* The same (memory behavior will be shown when running this test as normal TestNG test (e.g. using Intellij)
*/
public class MemoryLeakTestNg {
public static void main(String[] args) throws Exception {
// we run the test programmatically
runTest();
// lets wait for garbage collection
waitForAllObjectsDestructed();
}
public static void waitForAllObjectsDestructed() throws InterruptedException {
while (true) {
System.out.println("waiting for clean up...");
// enforce a full gc
System.gc();
// check if there are still instances of our test class
if (MyTestClassWithGlobalReferenceCounter.currentNumberOfMyTestObjects == 0) {
// if we reach this point, all test instances are gone,
// ... however this never happens ...
break;
}
// let's wait 5 seconds and try again ...
Thread.sleep(1000);
System.out.println("["+MyTestClassWithGlobalReferenceCounter.currentNumberOfMyTestObjects+"] test object(s) still exist.");
}
}
private static void runTest() {
// create TestNG class
TestNG testng = new TestNG() {
@Override
protected void finalize() throws Throwable {
// it seems that this object will never be finalized !!!
System.out.println("TestNG finalized");
}
};
// and set a test (which also will never be finalized ... see later)
testng.setTestClasses(new Class[]{
MyTestClassWithGlobalReferenceCounter.class,
});
// lets run the test
testng.run();
// At this point the test run through and we expect both instances
// - testng and
// - the test object of type (MyTest)
// will be garbage collected when leaving this method
// ...
}
/** we create a test NG class here, which has a global counter, counting all instances. */
public static class MyTestClassWithGlobalReferenceCounter {
/** global counter that keeps track on how many objects are currently on the heap */
public static int currentNumberOfMyTestObjects = 0;
public MyTestClassWithGlobalReferenceCounter() {
System.out.println("constructor");
// increase the counter
++currentNumberOfMyTestObjects;
}
@Test
public void aTestMethod1() {
System.out.println("test method 1");
}
@Test
public void aTestMethod2() {
System.out.println("test method 2");
}
@Override
protected void finalize() throws Throwable {
System.out.println("finalize");
// this will be called when this object is removed from the heap
--currentNumberOfMyTestObjects;
}
}
}
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Comments: 18 (9 by maintainers)
Commits related to this issue
- Fixed issue with TestNG not getting garbage collected. See #1461 — committed to kiru/testng by kiru 7 years ago
- Add test case for #1461 — committed to juherr/testng by juherr 7 years ago
- Fixes #1461: TestNG not getting garbage collected — committed to juherr/testng by juherr 7 years ago
- Merge branch 'master' into issue-#1461 — committed to juherr/testng by juherr 7 years ago
- Add test case for #1461 — committed to juherr/testng by juherr 7 years ago
- Fixes #1461: TestNG not getting garbage collected — committed to juherr/testng by juherr 7 years ago
- Merge pull request #1482 from juherr/issue-#1461 Fix Issue #1461: TestNG not getting garbage collected — committed to testng-team/testng by cbeust 7 years ago
@Pr0methean try using Guava’s
GcFinalizationwhich does a good job before failing on a timeout.