Skip to content

Commit 676cf3e

Browse files
8259046: ViewPainter.ROOT_PATHS holds reference to Scene causing memory leak
Reviewed-by: pbansal, arapte
1 parent d4058a1 commit 676cf3e

File tree

2 files changed

+116
-0
lines changed

2 files changed

+116
-0
lines changed

modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/ViewPainter.java

+1
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ protected void paintImpl(final Graphics backBufferGraphics) {
319319
g.setClipRect(dirtyRect);
320320
g.setClipRectIndex(i);
321321
doPaint(g, getRootPath(i));
322+
getRootPath(i).clear();
322323
}
323324
}
324325
} else {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
26+
package test.com.sun.javafx.tk.quantum;
27+
28+
import java.lang.ref.WeakReference;
29+
import java.util.concurrent.CountDownLatch;
30+
import java.util.concurrent.TimeUnit;
31+
import javafx.application.Application;
32+
import javafx.application.Platform;
33+
import javafx.scene.Scene;
34+
import javafx.scene.control.ScrollPane;
35+
import javafx.scene.layout.StackPane;
36+
import javafx.scene.text.Text;
37+
import javafx.scene.text.TextFlow;
38+
import javafx.stage.Stage;
39+
import javafx.stage.WindowEvent;
40+
import org.junit.AfterClass;
41+
import org.junit.BeforeClass;
42+
import org.junit.Test;
43+
import test.util.Util;
44+
import test.util.memory.JMemoryBuddy;
45+
46+
import static org.junit.Assert.*;
47+
48+
public class ViewPainterLeakTest {
49+
50+
private static CountDownLatch startupLatch;
51+
private static Stage stage;
52+
private static ScrollPane scrollPane;
53+
private static WeakReference<Scene> sceneRef;
54+
55+
private static final String text =
56+
"The quick brown fox jumps over the lazy dog." +
57+
" " +
58+
"The quick brown fox jumps over the lazy dog.";
59+
60+
public static class TestApp extends Application {
61+
@Override
62+
public void start(Stage stage) {
63+
ViewPainterLeakTest.stage = stage;
64+
65+
Platform.setImplicitExit(false);
66+
67+
TextFlow content = new TextFlow(new Text(text));
68+
scrollPane = new ScrollPane(content);
69+
StackPane root = new StackPane(scrollPane);
70+
71+
Scene scene = new Scene(root, 200, 100);
72+
sceneRef = new WeakReference<>(scene);
73+
stage.setScene(scene);
74+
75+
stage.addEventHandler(WindowEvent.WINDOW_SHOWN, e -> {
76+
Platform.runLater(() -> {
77+
startupLatch.countDown();
78+
});
79+
});
80+
stage.show();
81+
}
82+
}
83+
84+
@BeforeClass
85+
public static void setupOnce() throws Exception {
86+
startupLatch = new CountDownLatch(1);
87+
new Thread(() -> Application.launch(TestApp.class, (String[]) null)).start();
88+
assertTrue("Timeout waiting for FX runtime to start",
89+
startupLatch.await(15, TimeUnit.SECONDS));
90+
}
91+
92+
@AfterClass
93+
public static void teardown() {
94+
Platform.exit();
95+
}
96+
97+
@Test
98+
public void testViewPainterLeak() {
99+
// Wait for some time to make sure the initial content is displayed
100+
Util.sleep(500);
101+
102+
// This will trigger the leak
103+
Util.runAndWait(() -> scrollPane.setHvalue(0.5));
104+
105+
// Wait for some time to make sure the scrolled content is displayed
106+
Util.sleep(500);
107+
Util.runAndWait(() -> {
108+
stage.hide();
109+
stage = null;
110+
scrollPane = null;
111+
});
112+
JMemoryBuddy.assertCollectable(sceneRef);
113+
}
114+
115+
}

0 commit comments

Comments
 (0)