diff --git a/jdk/src/share/classes/java/awt/Window.java b/jdk/src/share/classes/java/awt/Window.java index 7471683749e..1994f479521 100644 --- a/jdk/src/share/classes/java/awt/Window.java +++ b/jdk/src/share/classes/java/awt/Window.java @@ -226,6 +226,7 @@ public class Window extends Container implements Accessible { 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 @@ public class Window extends Container implements Accessible { transient Object anchor = new Object(); static class WindowDisposerRecord implements sun.java2d.DisposerRecord { - final WeakReference owner; + WeakReference owner; final WeakReference weakThis; final WeakReference context; + WindowDisposerRecord(AppContext context, Window victim) { - owner = new WeakReference(victim.getOwner()); weakThis = victim.weakThis; this.context = new WeakReference(context); } + + public void updateOwner() { + Window victim = weakThis.get(); + owner = (victim == null) + ? null + : new WeakReference(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 @@ public class Window extends Container implements Accessible { } modalExclusionType = Dialog.ModalExclusionType.NO_EXCLUDE; + disposerRecord = new WindowDisposerRecord(appContext, this); + sun.java2d.Disposer.addRecord(anchor, disposerRecord); SunToolkit.checkAndSetPolicy(this); } @@ -619,9 +632,8 @@ public class Window extends Container implements Accessible { 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 @@ public class Window extends Container implements Accessible { void connectOwnedWindow(Window child) { child.parent = this; addOwnedWindow(child.weakThis); + child.disposerRecord.updateOwner(); } private void addToWindowList() { @@ -2936,7 +2949,8 @@ public class Window extends Container implements Accessible { 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); diff --git a/jdk/test/java/awt/Window/WindowsLeak/WindowsLeak.java b/jdk/test/java/awt/Window/WindowsLeak/WindowsLeak.java new file mode 100644 index 00000000000..dd776a8d299 --- /dev/null +++ b/jdk/test/java/awt/Window/WindowsLeak/WindowsLeak.java @@ -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> windowList = + (Vector>) 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"); + } +}