1.1 --- a/src/share/classes/java/awt/KeyboardFocusManager.java Thu Mar 29 13:02:24 2012 -0700
1.2 +++ b/src/share/classes/java/awt/KeyboardFocusManager.java Thu Sep 29 15:11:10 2011 -0700
1.3 @@ -38,6 +38,7 @@
1.4 import java.beans.VetoableChangeListener;
1.5 import java.beans.VetoableChangeSupport;
1.6
1.7 +import java.lang.ref.Reference;
1.8 import java.lang.ref.WeakReference;
1.9
1.10 import java.lang.reflect.Field;
1.11 @@ -56,7 +57,6 @@
1.12 import sun.util.logging.PlatformLogger;
1.13
1.14 import sun.awt.AppContext;
1.15 -import sun.awt.HeadlessToolkit;
1.16 import sun.awt.SunToolkit;
1.17 import sun.awt.CausedFocusEvent;
1.18 import sun.awt.KeyboardFocusManagerPeerProvider;
1.19 @@ -287,19 +287,19 @@
1.20 * The Component in an application that will typically receive all
1.21 * KeyEvents generated by the user.
1.22 */
1.23 - private static Component focusOwner;
1.24 + private static Reference<Component> focusOwner = new WeakReference<>(null);
1.25
1.26 /**
1.27 * The Component in an application that will regain focus when an
1.28 * outstanding temporary focus transfer has completed, or the focus owner,
1.29 * if no outstanding temporary transfer exists.
1.30 */
1.31 - private static Component permanentFocusOwner;
1.32 + private static Reference<Component> permanentFocusOwner = new WeakReference<>(null);;
1.33
1.34 /**
1.35 * The Window which is, or contains, the focus owner.
1.36 */
1.37 - private static Window focusedWindow;
1.38 + private static Reference<Window> focusedWindow = new WeakReference<>(null);
1.39
1.40 /**
1.41 * Only a Frame or a Dialog can be the active Window. The native windowing
1.42 @@ -308,7 +308,7 @@
1.43 * Window, or the first Frame or Dialog which is an owner of the focused
1.44 * Window.
1.45 */
1.46 - private static Window activeWindow;
1.47 + private static Reference<Window> activeWindow = new WeakReference<>(null);
1.48
1.49 /**
1.50 * The default FocusTraversalPolicy for all Windows that have no policy of
1.51 @@ -475,12 +475,13 @@
1.52 */
1.53 public Component getFocusOwner() {
1.54 synchronized (KeyboardFocusManager.class) {
1.55 - if (focusOwner == null) {
1.56 + final Component owner = focusOwner.get();
1.57 + if (owner == null) {
1.58 return null;
1.59 }
1.60
1.61 - return (focusOwner.appContext == AppContext.getAppContext())
1.62 - ? focusOwner
1.63 + return (owner.appContext == AppContext.getAppContext())
1.64 + ? owner
1.65 : null;
1.66 }
1.67 }
1.68 @@ -506,8 +507,9 @@
1.69 */
1.70 protected Component getGlobalFocusOwner() throws SecurityException {
1.71 synchronized (KeyboardFocusManager.class) {
1.72 + Component owner = focusOwner.get();
1.73 if (this == getCurrentKeyboardFocusManager()) {
1.74 - return focusOwner;
1.75 + return owner;
1.76 } else {
1.77 if (focusLog.isLoggable(PlatformLogger.FINER)) {
1.78 focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
1.79 @@ -557,7 +559,7 @@
1.80 return;
1.81 }
1.82
1.83 - KeyboardFocusManager.focusOwner = focusOwner;
1.84 + KeyboardFocusManager.focusOwner = new WeakReference<>(focusOwner);
1.85
1.86 if (focusOwner != null &&
1.87 (getCurrentFocusCycleRoot() == null ||
1.88 @@ -641,13 +643,14 @@
1.89 */
1.90 public Component getPermanentFocusOwner() {
1.91 synchronized (KeyboardFocusManager.class) {
1.92 - if (permanentFocusOwner == null) {
1.93 + Component permaOwner = permanentFocusOwner.get();
1.94 + if (permaOwner == null) {
1.95 return null;
1.96 }
1.97
1.98 - return (permanentFocusOwner.appContext ==
1.99 + return (permaOwner.appContext ==
1.100 AppContext.getAppContext())
1.101 - ? permanentFocusOwner
1.102 + ? permaOwner
1.103 : null;
1.104 }
1.105 }
1.106 @@ -675,8 +678,9 @@
1.107 throws SecurityException
1.108 {
1.109 synchronized (KeyboardFocusManager.class) {
1.110 + Component permaOwner = permanentFocusOwner.get();
1.111 if (this == getCurrentKeyboardFocusManager()) {
1.112 - return permanentFocusOwner;
1.113 + return permaOwner;
1.114 } else {
1.115 if (focusLog.isLoggable(PlatformLogger.FINER)) {
1.116 focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
1.117 @@ -729,7 +733,7 @@
1.118 return;
1.119 }
1.120
1.121 - KeyboardFocusManager.permanentFocusOwner = permanentFocusOwner;
1.122 + KeyboardFocusManager.permanentFocusOwner = new WeakReference<>(permanentFocusOwner);
1.123
1.124 KeyboardFocusManager.
1.125 setMostRecentFocusOwner(permanentFocusOwner);
1.126 @@ -756,12 +760,13 @@
1.127 */
1.128 public Window getFocusedWindow() {
1.129 synchronized (KeyboardFocusManager.class) {
1.130 - if (focusedWindow == null) {
1.131 + Window win = focusedWindow.get();
1.132 + if (win == null) {
1.133 return null;
1.134 }
1.135
1.136 - return (focusedWindow.appContext == AppContext.getAppContext())
1.137 - ? focusedWindow
1.138 + return (win.appContext == AppContext.getAppContext())
1.139 + ? win
1.140 : null;
1.141 }
1.142 }
1.143 @@ -783,8 +788,9 @@
1.144 */
1.145 protected Window getGlobalFocusedWindow() throws SecurityException {
1.146 synchronized (KeyboardFocusManager.class) {
1.147 + Window win = focusedWindow.get();
1.148 if (this == getCurrentKeyboardFocusManager()) {
1.149 - return focusedWindow;
1.150 + return win;
1.151 } else {
1.152 if (focusLog.isLoggable(PlatformLogger.FINER)) {
1.153 focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
1.154 @@ -831,7 +837,7 @@
1.155 return;
1.156 }
1.157
1.158 - KeyboardFocusManager.focusedWindow = focusedWindow;
1.159 + KeyboardFocusManager.focusedWindow = new WeakReference<>(focusedWindow);
1.160 shouldFire = true;
1.161 }
1.162 }
1.163 @@ -857,12 +863,13 @@
1.164 */
1.165 public Window getActiveWindow() {
1.166 synchronized (KeyboardFocusManager.class) {
1.167 - if (activeWindow == null) {
1.168 + Window active = activeWindow.get();
1.169 + if (active == null) {
1.170 return null;
1.171 }
1.172
1.173 - return (activeWindow.appContext == AppContext.getAppContext())
1.174 - ? activeWindow
1.175 + return (active.appContext == AppContext.getAppContext())
1.176 + ? active
1.177 : null;
1.178 }
1.179 }
1.180 @@ -888,7 +895,7 @@
1.181 protected Window getGlobalActiveWindow() throws SecurityException {
1.182 synchronized (KeyboardFocusManager.class) {
1.183 if (this == getCurrentKeyboardFocusManager()) {
1.184 - return activeWindow;
1.185 + return activeWindow.get();
1.186 } else {
1.187 if (focusLog.isLoggable(PlatformLogger.FINER)) {
1.188 focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
1.189 @@ -936,7 +943,7 @@
1.190 return;
1.191 }
1.192
1.193 - KeyboardFocusManager.activeWindow = activeWindow;
1.194 + KeyboardFocusManager.activeWindow = new WeakReference<>(activeWindow);
1.195 }
1.196
1.197 firePropertyChange("activeWindow", oldActiveWindow, activeWindow);
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/test/java/awt/KeyboardFocusmanager/MemoryLeaks/LeakViaActiveWindow.java Thu Sep 29 15:11:10 2011 -0700
2.3 @@ -0,0 +1,35 @@
2.4 +/*
2.5 + @test
2.6 + @bug 7070542
2.7 + @summary KeyboardFocusManager.activeWindow leaks references to components
2.8 + @library ../../regtesthelpers
2.9 + @author Jaroslav Tulach
2.10 + @run main LeakViaActiveWindow
2.11 +*/
2.12 +
2.13 +import java.awt.*;
2.14 +import java.lang.ref.Reference;
2.15 +import java.lang.ref.WeakReference;
2.16 +import javax.swing.JFrame;
2.17 +
2.18 +public class LeakViaActiveWindow {
2.19 + public static void main(String []s) {
2.20 + LeakViaFocusOwner.AccessibleKeyboarFocusManager access = new LeakViaFocusOwner.AccessibleKeyboarFocusManager();
2.21 + KeyboardFocusManager currentKFM = KeyboardFocusManager.getCurrentKeyboardFocusManager();
2.22 +
2.23 + JFrame frame = new JFrame();
2.24 + access.setActiveWindow(frame);
2.25 +
2.26 + if (frame != currentKFM.getActiveWindow()) {
2.27 + throw new RuntimeException("Our frame is not focus owner: " + currentKFM.getActiveWindow());
2.28 + }
2.29 +
2.30 + Reference<Object> ref = new WeakReference<Object>(frame);
2.31 + frame = null;
2.32 + LeakViaFocusOwner.assertGC("frame can disappear", ref);
2.33 +
2.34 + if (currentKFM.getActiveWindow() != null) {
2.35 + throw new RuntimeException("Now the owner is GC and thus should be null: " + currentKFM.getActiveWindow());
2.36 + }
2.37 + }
2.38 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/test/java/awt/KeyboardFocusmanager/MemoryLeaks/LeakViaFocusOwner.java Thu Sep 29 15:11:10 2011 -0700
3.3 @@ -0,0 +1,147 @@
3.4 +/*
3.5 + @test
3.6 + @bug 7070542
3.7 + @summary KeyboardFocusManager.focusOwner leaks references to components
3.8 + @library ../../regtesthelpers
3.9 + @author Jaroslav Tulach
3.10 + @run main LeakViaFocusOwner
3.11 +*/
3.12 +
3.13 +import java.awt.*;
3.14 +import java.awt.event.KeyEvent;
3.15 +import java.lang.ref.Reference;
3.16 +import java.lang.ref.WeakReference;
3.17 +import javax.swing.JButton;
3.18 +import java.util.List;
3.19 +import java.util.ArrayList;
3.20 +
3.21 +public class LeakViaFocusOwner {
3.22 + public static void main(String []s) {
3.23 + runTestAWT();
3.24 + }
3.25 +
3.26 + private static void runTestAWT(){
3.27 + AccessibleKeyboarFocusManager access = new AccessibleKeyboarFocusManager();
3.28 + KeyboardFocusManager currentKFM = KeyboardFocusManager.getCurrentKeyboardFocusManager();
3.29 +
3.30 + JButton button = new JButton();
3.31 + access.setFocusOwner(button);
3.32 +
3.33 + if (button != currentKFM.getFocusOwner()) {
3.34 + throw new RuntimeException("Our button is not focus owner: " + currentKFM.getFocusOwner());
3.35 + }
3.36 +
3.37 + Reference<Object> ref = new WeakReference<Object>(button);
3.38 + button = null;
3.39 + assertGC("Button can disappear", ref);
3.40 +
3.41 + if (currentKFM.getFocusOwner() != null) {
3.42 + throw new RuntimeException("Now the owner is GC and thus should be null: " + currentKFM.getFocusOwner());
3.43 + }
3.44 + }
3.45 +
3.46 + public static void assertGC(final String text, final Reference<?> ref) {
3.47 + List<byte[]> alloc = new ArrayList<byte[]>();
3.48 + int size = 100000;
3.49 + for (int i = 0; i < 50; i++) {
3.50 + if (ref.get() == null) {
3.51 + return;
3.52 + }
3.53 + try {
3.54 + System.gc();
3.55 + } catch (OutOfMemoryError error) {
3.56 + // OK
3.57 + }
3.58 + try {
3.59 + System.runFinalization();
3.60 + } catch (OutOfMemoryError error) {
3.61 + // OK
3.62 + }
3.63 + try {
3.64 + alloc.add(new byte[size]);
3.65 + size = (int) (((double) size) * 1.3);
3.66 + } catch (OutOfMemoryError error) {
3.67 + size = size / 2;
3.68 + }
3.69 + try {
3.70 + if (i % 3 == 0) {
3.71 + Thread.sleep(321);
3.72 + }
3.73 + } catch (InterruptedException t) {
3.74 + // ignore
3.75 + }
3.76 + }
3.77 + alloc = null;
3.78 + throw new IllegalStateException(text);
3.79 + }
3.80 +
3.81 + public static final class AccessibleKeyboarFocusManager extends KeyboardFocusManager {
3.82 + public void setFocusOwner(Component c) {
3.83 + super.setGlobalFocusOwner(c);
3.84 + }
3.85 +
3.86 + public void setFocusedWindow(Window w) {
3.87 + super.setGlobalFocusedWindow(w);
3.88 + }
3.89 +
3.90 + public void setActiveWindow(Window w) {
3.91 + super.setGlobalActiveWindow(w);
3.92 + }
3.93 +
3.94 + @Override
3.95 + public boolean dispatchEvent(AWTEvent e) {
3.96 + throw new UnsupportedOperationException("Not supported yet.");
3.97 + }
3.98 +
3.99 + @Override
3.100 + public boolean dispatchKeyEvent(KeyEvent e) {
3.101 + throw new UnsupportedOperationException("Not supported yet.");
3.102 + }
3.103 +
3.104 + @Override
3.105 + public boolean postProcessKeyEvent(KeyEvent e) {
3.106 + throw new UnsupportedOperationException("Not supported yet.");
3.107 + }
3.108 +
3.109 + @Override
3.110 + public void processKeyEvent(Component focusedComponent, KeyEvent e) {
3.111 + throw new UnsupportedOperationException("Not supported yet.");
3.112 + }
3.113 +
3.114 + @Override
3.115 + protected void enqueueKeyEvents(long after, Component untilFocused) {
3.116 + throw new UnsupportedOperationException("Not supported yet.");
3.117 + }
3.118 +
3.119 + @Override
3.120 + protected void dequeueKeyEvents(long after, Component untilFocused) {
3.121 + throw new UnsupportedOperationException("Not supported yet.");
3.122 + }
3.123 +
3.124 + @Override
3.125 + protected void discardKeyEvents(Component comp) {
3.126 + throw new UnsupportedOperationException("Not supported yet.");
3.127 + }
3.128 +
3.129 + @Override
3.130 + public void focusNextComponent(Component aComponent) {
3.131 + throw new UnsupportedOperationException("Not supported yet.");
3.132 + }
3.133 +
3.134 + @Override
3.135 + public void focusPreviousComponent(Component aComponent) {
3.136 + throw new UnsupportedOperationException("Not supported yet.");
3.137 + }
3.138 +
3.139 + @Override
3.140 + public void upFocusCycle(Component aComponent) {
3.141 + throw new UnsupportedOperationException("Not supported yet.");
3.142 + }
3.143 +
3.144 + @Override
3.145 + public void downFocusCycle(Container aContainer) {
3.146 + throw new UnsupportedOperationException("Not supported yet.");
3.147 + }
3.148 +
3.149 + }
3.150 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/test/java/awt/KeyboardFocusmanager/MemoryLeaks/LeakViaFocusedWindow.java Thu Sep 29 15:11:10 2011 -0700
4.3 @@ -0,0 +1,35 @@
4.4 +/*
4.5 + @test
4.6 + @bug 7070542
4.7 + @summary KeyboardFocusManager.focusedWindow leaks references to components
4.8 + @library ../../regtesthelpers
4.9 + @author Jaroslav Tulach
4.10 + @run main LeakViaFocusedWindow
4.11 +*/
4.12 +
4.13 +import java.awt.*;
4.14 +import java.lang.ref.Reference;
4.15 +import java.lang.ref.WeakReference;
4.16 +import javax.swing.JFrame;
4.17 +
4.18 +public class LeakViaFocusedWindow {
4.19 + public static void main(String []s) {
4.20 + LeakViaFocusOwner.AccessibleKeyboarFocusManager access = new LeakViaFocusOwner.AccessibleKeyboarFocusManager();
4.21 + KeyboardFocusManager currentKFM = KeyboardFocusManager.getCurrentKeyboardFocusManager();
4.22 +
4.23 + JFrame frame = new JFrame();
4.24 + access.setFocusedWindow(frame);
4.25 +
4.26 + if (frame != currentKFM.getFocusedWindow()) {
4.27 + throw new RuntimeException("Our frame is not focus owner: " + currentKFM.getFocusedWindow());
4.28 + }
4.29 +
4.30 + Reference<Object> ref = new WeakReference<Object>(frame);
4.31 + frame = null;
4.32 + LeakViaFocusOwner.assertGC("frame can disappear", ref);
4.33 +
4.34 + if (currentKFM.getFocusedWindow() != null) {
4.35 + throw new RuntimeException("Now the owner is GC and thus should be null: " + currentKFM.getFocusedWindow());
4.36 + }
4.37 + }
4.38 +}