Describe the bug
When calling GC#drawImage(), an operation is create (like for every execution on GC) which stores the image to draw. Since the image may be disposed afterwards, a dispose listener is registered to the image, such that the image can be copied and maintained inside the operation in case of a disposal until that operation itself is disposed.
Since the listener is currently not deregistered when disposing the GC and its operations, the GC operations (and thus also the containing GC) will still be referenced (as listeners from the image) until that image is disposed. Since images may be long living (or never be disposed at all), this can lead to a memory leak.
To Reproduce
The following test will unexpectedly fail because the garbage collector cannot clean up the GC instance as it remains referenced from the image.
@Test
public void test_noMemoryLeakAfterDispose() {
GC testGC = new GC(display);
Image image = new Image(display, 1, 1);
testGC.setFont(display.getSystemFont());
testGC.setClipping(new Rectangle(0, 0, 2, 2));
testGC.drawImage(image, 0, 0);
testGC.drawText("Test", 0, 0);
testGC.drawLine(0, 0, 5, 5);
WeakReference<GC> testGCReference = new WeakReference<>(testGC);
testGC.dispose();
testGC = null;
System.gc();
assertNull(testGCReference.get());
}
The same can also be seen when investigating GC or GC$DrawImage operations in heap dumps when running an application that applies such a pattern.
Expected behavior
When disposing a GC, one of the next garbage collector runs should eliminate the GC and its operations from memory.
Environment:
- Select the platform(s) on which the behavior is seen:
Describe the bug
When calling
GC#drawImage(), an operation is create (like for every execution on GC) which stores the image to draw. Since the image may be disposed afterwards, a dispose listener is registered to the image, such that the image can be copied and maintained inside the operation in case of a disposal until that operation itself is disposed.Since the listener is currently not deregistered when disposing the GC and its operations, the GC operations (and thus also the containing GC) will still be referenced (as listeners from the image) until that image is disposed. Since images may be long living (or never be disposed at all), this can lead to a memory leak.
To Reproduce
The following test will unexpectedly fail because the garbage collector cannot clean up the GC instance as it remains referenced from the image.
The same can also be seen when investigating
GCorGC$DrawImageoperations in heap dumps when running an application that applies such a pattern.Expected behavior
When disposing a GC, one of the next garbage collector runs should eliminate the GC and its operations from memory.
Environment: