RFR: 8263402: MemoryLeak: Node hardreferences it's previous Parent after csslayout and getting removed from the scene

Ambarish Rapte arapte at openjdk.java.net
Fri Mar 12 07:59:09 UTC 2021


On Wed, 10 Mar 2021 22:25:32 GMT, Florian Kirmaier <fkirmaier at openjdk.org> wrote:

> Fixing a memory leak. 
> A node hard references its old parent after CSS layout and getting removed. 
> This shouldn't be the case, this is very counterintuitive.
> 
> The fix uses a WeakReference in CSSStyleHelper for firstStyleableAncestor.
> This should be fine because the CSS should only depend on it if it's still the real parent. 
> In that case, it doesn't get collected.

tests/system/src/test/java/test/javafx/scene/StyleMemoryLeakTest.java line 106:

> 104:         });
> 105:     }
> 106: }

In order to make this test similar to existing system tests, I made some relevant changes. Modified test is added below.
The modified test fails with this fix, but I expected it to pass. Can you please check this.

Changes are 
1. `Thread.sleep()` is removed.
2. `root` and `toBeRemoved` button are now class members.
3. Scenegraph is constructed and shown in `TestApp.start()` method.


public class StyleMemoryLeakTest {

    static CountDownLatch startupLatch;
    static Stage stage;
    static Button toBeRemoved;
    static Group root;

    public static class TestApp extends Application {

        @Override
        public void start(Stage primaryStage) throws Exception {
            stage = primaryStage;
            toBeRemoved = new Button();
            root = new Group();
            root.getChildren().add(toBeRemoved);
            stage.setScene(new Scene(root));
            stage.setOnShown(l -> {
                Platform.runLater(() -> startupLatch.countDown());
            });
            stage.show();
        }
    }

    @BeforeClass
    public static void initFX() throws Exception {
        startupLatch = new CountDownLatch(1);
        new Thread(() -> Application.launch(StyleMemoryLeakTest.TestApp.class, (String[])null)).start();
        assertTrue("Timeout waiting for FX runtime to start", startupLatch.await(15, TimeUnit.SECONDS));
    }

    @Test
    public void testRootNodeMemoryLeak() throws Exception {
        Util.runAndWait(() -> {
            root.getChildren().clear();
            stage.hide();
        });
        JMemoryBuddy.memoryTest((checker) -> {
            checker.assertCollectable(stage);
            checker.setAsReferenced(toBeRemoved);
            stage = null;
        });
    }

    @AfterClass
    public static void teardownOnce() {
        Platform.runLater(() -> {
            Platform.exit();
        });
    }
}

-------------

PR: https://git.openjdk.java.net/jfx/pull/424


More information about the openjfx-dev mailing list