import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
+
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
/*
* maximum retained heap usage (in MB) for a passing test
*/
- private static int MAX_RESIDUAL_HEAP = 38;
-
+ private static int MAX_RESIDUAL_HEAP = 45;
/**
* Configure (read-only) Jalview property settings for test
*/
new String[]
{ "-nonews", "-props", "test/jalview/testProps.jvprops" });
String True = Boolean.TRUE.toString();
- Cache.applicationProperties.setProperty("SHOW_ANNOTATIONS", True);
- Cache.applicationProperties.setProperty("SHOW_QUALITY", True);
- Cache.applicationProperties.setProperty("SHOW_CONSERVATION", True);
- Cache.applicationProperties.setProperty("SHOW_OCCUPANCY", True);
- Cache.applicationProperties.setProperty("SHOW_IDENTITY", True);
+ Cache.setPropertyNoSave("SHOW_ANNOTATIONS", True);
+ Cache.setPropertyNoSave("SHOW_QUALITY", True);
+ Cache.setPropertyNoSave("SHOW_CONSERVATION", True);
+ Cache.setPropertyNoSave("SHOW_OCCUPANCY", True);
+ Cache.setPropertyNoSave("SHOW_IDENTITY", True);
}
+ /**
+ * A simple test that memory is released when all windows are closed.
+ * <ul>
+ * <li>generates a reasonably large alignment and loads it</li>
+ * <li>performs various operations on the alignment</li>
+ * <li>closes all windows</li>
+ * <li>requests garbage collection</li>
+ * <li>asserts that the remaining memory footprint (heap usage) is 'not large'
+ * </li>
+ * </ul>
+ * If the test fails, this suggests that a reference to some large object
+ * (perhaps the alignment data, or some annotation / Tree / PCA data) has
+ * failed to be garbage collected. If this is the case, the heap will need to
+ * be inspected manually (suggest using jvisualvm) in order to track down
+ * where large objects are still referenced. The code (for example
+ * AlignmentViewport.dispose()) should then be updated to ensure references to
+ * large objects are set to null when they are no longer required.
+ *
+ * @throws IOException
+ */
@Test(groups = "Memory")
public void testFreeMemoryOnClose() throws IOException
{
File f = generateAlignment();
f.deleteOnExit();
+ long expectedMin = MAX_RESIDUAL_HEAP;
+ long usedMemoryAtStart=getUsedMemory();
+ if (usedMemoryAtStart>expectedMin)
+ {
+ System.err.println("used memory before test is "+usedMemoryAtStart+" > "+expectedMin+"MB .. adjusting minimum.");
+ expectedMin = usedMemoryAtStart;
+ }
doStuffInJalview(f);
- Desktop.instance.closeAll_actionPerformed(null);
+ Desktop.getInstance().closeAll_actionPerformed(null);
- checkUsedMemory(MAX_RESIDUAL_HEAP);
+ checkUsedMemory(expectedMin);
}
/**
long availableMemory = Runtime.getRuntime().totalMemory();
long freeMemory = Runtime.getRuntime().freeMemory();
long usedMemory = availableMemory - freeMemory;
-
- return (int) (usedMemory/ ONE_MB);
+ return (int) (usedMemory / ONE_MB);
}
-
/**
* Requests garbage collection and then checks whether remaining memory in use
* is less than the expected value (in Megabytes)
* NB there is no guarantee when, or whether, it will do so
*/
long usedMemory = 0L;
+ Long minUsedMemory = null;
int gcCount = 0;
while (gcCount < 3)
{
System.gc();
waitFor(1500);
usedMemory = getUsedMemory();
+ if (minUsedMemory == null || usedMemory < minUsedMemory)
+ {
+ minUsedMemory = usedMemory;
+ }
if (usedMemory < expectedMax)
{
break;
* - take a heap dump and identify large objects in the heap and their referers
* - fix code as necessary to null the references on close
*/
- System.out
- .println("Used memory after " + gcCount + " call(s) to gc() = "
- + usedMemory + "MB (should be <=" + expectedMax + ")");
+ System.out.println("(Minimum) Used memory after " + gcCount
+ + " call(s) to gc() = " + minUsedMemory + "MB (should be <="
+ + expectedMax + ")");
assertTrue(usedMemory <= expectedMax, String.format(
"Used memory %d should be less than %d (Recommend running test manually to verify)",
usedMemory, expectedMax));