5

I have a java class that might allocate a lot of data.

I have written a junit test that should check for memory leaks similar to the code below.

Unfortunatley the test fails.

@Test
public void shoudNotMemoryLeak()
{
    Runtime runtime = Runtime.getRuntime();
    // make shure that gc has collected all
    System.gc ();
    System.runFinalization ();

    // memory before creating my sut
    long memoryUsedBefore = runtime.freeMemory();
    long memoryUsedAfter = 0;

    // this consumes memory
    StringBuilder sut = new StringBuilder("hello world");

    // make memory available to gc
    sut = null;

    // make shure that gc has collected all
    System.gc ();
    System.runFinalization ();

    // memory after creating my sut
    memoryUsedAfter = runtime.freeMemory();

    // this fails 
    assertEquals(memoryUsedAfter, memoryUsedBefore);
}

Any ideas how to modify the junittest to check for memoryleaks?

[update]

unfortunatley the 9 year old possible duplicate did not provide a sulution to my question

I changed the title and content to make it more specific than the "possible duplicate candidate"

k3b
  • 14,517
  • 7
  • 53
  • 85
  • Possible duplicate of [Automated way to find JUnit tests that leak memory](https://stackoverflow.com/questions/863948/automated-way-to-find-junit-tests-that-leak-memory) – Micheal O'Dwyer Feb 09 '18 at 16:21
  • 2
    I don't think unit tests who are performing garbage collection are the way to find memory leaks. What you should do is crate unit test that test functionality and then check that objects are no longer referenced in the class you test ( for example a class has a list field, you should check that the list no longer contains the not needed objects). – Zpetkov Feb 09 '18 at 16:25
  • String was only meant as a simplified memory-consumer-example. I actually have an android app with in-memory-file-directory-structure with recursive links from parent-directory containing sub-directories and sub-directories knowing its parent-directory. There is a free-directory-method that should eliminate all references before disposing the memory and i thought having an automated regression test that checks that cleanup memory still works would be a good idea. After 9 months i have given up ;-( – k3b Nov 20 '18 at 15:52

1 Answers1

4

There are couple of problems when testing memory leak with unit tests;
Firstly, In Javadoc, running System.gc() and System.runFinalization() does not seem to guarantee collection and finalization to be happened, because it mentions as "best effort"

Calling the gc method suggests that the Java Virtual Machine expend effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse. When control returns from the method call, the Java Virtual Machine has made a best effort to reclaim space from all discarded objects.

Runs the finalization methods of any objects pending finalization. Calling this method suggests that the Java Virtual Machine expend effort toward running the finalize methods of objects that have been found to be discarded but whose finalize methods have not yet been run. When control returns from the method call, the Java Virtual Machine has made a best effort to complete all outstanding finalizations.

Secondly, Runtime.freeMemory() documented as "returns approximation"

an approximation to the total amount of memory currently available for future allocated objects, measured in bytes.

Thirdly, I know you give "String" as example, but according to this thread String literals are not garbage collected until the class that declares them is unloaded. Garbage collection of String literals

So I don't think it is something that can be unit testable. I would use profilers if I wanted to find memory leaks.

miskender
  • 7,460
  • 1
  • 19
  • 23
  • 1
    Sadly after 9 months i have to accept this answer that tells me: it is not possible ;-( – k3b Nov 20 '18 at 15:55