OpenJDK / portola / portola
changeset 20450:008da09ac2b2
8013563: Memory leak in JFrame on Linux
Reviewed-by: anthony, art
author | serb |
---|---|
date | Wed, 02 Oct 2013 21:02:04 +0400 |
parents | 20326f6cd2aa |
children | 4cedf4e1560a |
files | jdk/src/share/classes/java/awt/Window.java jdk/test/java/awt/Window/WindowsLeak/WindowsLeak.java |
diffstat | 2 files changed, 93 insertions(+), 8 deletions(-) [+] |
line wrap: on
line diff
--- a/jdk/src/share/classes/java/awt/Window.java Wed Oct 02 17:06:09 2013 +0400 +++ b/jdk/src/share/classes/java/awt/Window.java Wed Oct 02 21:02:04 2013 +0400 @@ -226,6 +226,7 @@ boolean syncLWRequests = false; transient boolean beforeFirstShow = true; private transient boolean disposing = false; + transient WindowDisposerRecord disposerRecord = null; static final int OPENED = 0x01; @@ -437,18 +438,28 @@ transient Object anchor = new Object(); static class WindowDisposerRecord implements sun.java2d.DisposerRecord { - final WeakReference<Window> owner; + WeakReference<Window> owner; final WeakReference<Window> weakThis; final WeakReference<AppContext> context; + WindowDisposerRecord(AppContext context, Window victim) { - owner = new WeakReference<Window>(victim.getOwner()); weakThis = victim.weakThis; this.context = new WeakReference<AppContext>(context); } + + public void updateOwner() { + Window victim = weakThis.get(); + owner = (victim == null) + ? null + : new WeakReference<Window>(victim.getOwner()); + } + public void dispose() { - Window parent = owner.get(); - if (parent != null) { - parent.removeOwnedWindow(weakThis); + if (owner != null) { + Window parent = owner.get(); + if (parent != null) { + parent.removeOwnedWindow(weakThis); + } } AppContext ac = context.get(); if (null != ac) { @@ -502,6 +513,8 @@ } modalExclusionType = Dialog.ModalExclusionType.NO_EXCLUDE; + disposerRecord = new WindowDisposerRecord(appContext, this); + sun.java2d.Disposer.addRecord(anchor, disposerRecord); SunToolkit.checkAndSetPolicy(this); } @@ -619,9 +632,8 @@ owner.addOwnedWindow(weakThis); } - // Fix for 6758673: this call is moved here from init(gc), because // WindowDisposerRecord requires a proper value of parent field. - Disposer.addRecord(anchor, new WindowDisposerRecord(appContext, this)); + disposerRecord.updateOwner(); } /** @@ -2774,6 +2786,7 @@ void connectOwnedWindow(Window child) { child.parent = this; addOwnedWindow(child.weakThis); + child.disposerRecord.updateOwner(); } private void addToWindowList() { @@ -2936,7 +2949,8 @@ weakThis = new WeakReference<>(this); anchor = new Object(); - sun.java2d.Disposer.addRecord(anchor, new WindowDisposerRecord(appContext, this)); + disposerRecord = new WindowDisposerRecord(appContext, this); + sun.java2d.Disposer.addRecord(anchor, disposerRecord); addToWindowList(); initGC(null);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/Window/WindowsLeak/WindowsLeak.java Wed Oct 02 21:02:04 2013 +0400 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8013563 + * @summary Tests that windows are removed from windows list + * @run main/othervm -Xms32M -Xmx32M WindowsLeak +*/ + +import java.awt.*; +import sun.awt.AppContext; + +import java.lang.ref.WeakReference; + +import java.util.Vector; + +public class WindowsLeak { + + public static void main(String[] args) { + for (int i = 0; i < 100; i++) + { + Frame f = new Frame(); + f.pack(); + f.dispose(); + } + + Vector garbage = new Vector(); + while (true) + { + try + { + garbage.add(new byte[1000]); + } + catch (OutOfMemoryError e) + { + break; + } + } + garbage = null; + + Vector<WeakReference<Window>> windowList = + (Vector<WeakReference<Window>>) AppContext.getAppContext().get(Window.class); + + if (windowList != null && !windowList.isEmpty()) { + throw new RuntimeException("Test FAILED: Window list is not empty: " + windowList.size()); + } + + System.out.println("Test PASSED"); + } +}