Skip to content

[Win32] GC#drawImage can produce memory leak #2499

Description

@HeikoKlare

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:

  1. Select the platform(s) on which the behavior is seen:
    • All OS
    • Windows
    • Linux
    • macOS

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions