This fixes the following potential problems in AWT:
- The Frame.weakFrames list could be filled up with GCed Frame
references. This is avoided by holding a ReferenceQueue that gets polled
regularily and removes stale entries.
- In getFrames() there was a chance that null entries sneak in the
resulting array because we iterate 2 times over the list and can't be
sure that no Frame gets GCed in the meantime. This is solved by
iterating only once and 'pin' the frame instance in this iteration.
- The displayable frame checking code in EventQueue.isShutdown() is
moved into Frame for more beautiful code and better encapsulation of
functionality.
2007-04-04 Roman Kennke <[EMAIL PROTECTED]>
* java/awt/Frame.java
(weakFrames): Make private.
(weakFramesQueue): New field. A reference queue to collect
GCed references.
(getFrames): Only do one iterations to avoid collecting null
references.
(hasDisplayableFrames): New helper method. Checks if there
are any displayable frames. This is used by the event queue
shutdown check.
(noteFrame): Clean up GCed frames in the list.
* java/awt/EventQueue.java
(isShutdown): Move frame checking code into Frame.
/Roman
--
aicas Allerton Interworks Computer Automated Systems GmbH
Haid-und-Neu-Straße 18 * D-76131 Karlsruhe * Germany
http://www.aicas.com * Tel: +49-721-663 968-0
USt-Id: DE216375633, Handelsregister HRB 109481, AG Karlsruhe
Geschäftsführer: Dr. James J. Hunt
Index: java/awt/Frame.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/awt/Frame.java,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -1 -5 -r1.42 -r1.43
--- java/awt/Frame.java 27 Mar 2007 09:34:50 -0000 1.42
+++ java/awt/Frame.java 4 Apr 2007 10:15:15 -0000 1.43
@@ -28,33 +28,34 @@
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.awt;
import java.awt.peer.FramePeer;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
-import java.util.Iterator;
import java.util.Vector;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
import javax.accessibility.AccessibleState;
import javax.accessibility.AccessibleStateSet;
/**
* This class is a top-level window with a title bar and window
* decorations.
*
* @author Aaron M. Renn ([EMAIL PROTECTED])
*/
public class Frame extends Window implements MenuContainer
{
@@ -473,72 +474,95 @@
case MAXIMIZED_BOTH:
state = ",maximized-both";
break;
case MAXIMIZED_HORIZ:
state = ",maximized-horiz";
break;
case MAXIMIZED_VERT:
state = ",maximized-vert";
break;
}
return super.paramString () + ",title=" + title + resizable + state;
}
/**
- * This is static private because we need to access this efficiently from
- * the EventQueue.
+ * The list of active frames. GC'ed frames get removed in noteFrame().
*/
- static ArrayList<WeakReference<Frame>> weakFrames =
+ private static ArrayList<WeakReference<Frame>> weakFrames =
new ArrayList<WeakReference<Frame>>();
+ /**
+ * The death queue for all frames.
+ */
+ private static ReferenceQueue weakFramesQueue =
+ new ReferenceQueue<Frame>();
+
private static void noteFrame(Frame f)
{
synchronized (weakFrames)
{
+ // Remove GCed frames from the list.
+ Reference ref = weakFramesQueue.poll();
+ while (ref != null)
+ {
+ weakFrames.remove(ref);
+ ref = weakFramesQueue.poll();
+ }
+ // Add new frame.
weakFrames.add(new WeakReference<Frame>(f));
}
}
+ /**
+ * Returns <code>true</code> when there are any displayable frames,
+ * <code>false</code> otherwise.
+ *
+ * @return <code>true</code> when there are any displayable frames,
+ * <code>false</code> otherwise
+ */
+ static boolean hasDisplayableFrames()
+ {
+ synchronized (weakFrames)
+ {
+ for (WeakReference<Frame> r : Frame.weakFrames)
+ {
+ Frame f = (Frame) r.get();
+ if (f != null && f.isDisplayable())
+ return true;
+ }
+ }
+ return false;
+ }
+
public static Frame[] getFrames()
{
- int n = 0;
synchronized (weakFrames)
- {
- Iterator i = weakFrames.iterator();
- while (i.hasNext())
- {
- WeakReference wr = (WeakReference) i.next();
- if (wr.get() != null)
- ++n;
- }
- if (n == 0)
- return new Frame[0];
- else
- {
- Frame[] frames = new Frame[n];
- n = 0;
- i = weakFrames.iterator();
- while (i.hasNext())
- {
- WeakReference wr = (WeakReference) i.next();
- if (wr.get() != null)
- frames[n++] = (Frame) wr.get();
- }
- return frames;
- }
- }
+ {
+ ArrayList<Frame> existingFrames = new ArrayList<Frame>();
+ for (WeakReference<Frame> ref : weakFrames)
+ {
+ Frame f = ref.get();
+ if (f != null)
+ {
+ existingFrames.add(f);
+ }
+ }
+ Frame[] frames = new Frame[existingFrames.size()];
+ frames = existingFrames.toArray(frames);
+ return frames;
+ }
}
public void setState(int state)
{
int current_state = getExtendedState ();
if (state == NORMAL
&& (current_state & ICONIFIED) != 0)
setExtendedState(current_state | ICONIFIED);
if (state == ICONIFIED
&& (current_state & ~ICONIFIED) == 0)
setExtendedState(current_state & ~ICONIFIED);
}
Index: java/awt/EventQueue.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/awt/EventQueue.java,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -1 -5 -r1.33 -r1.34
--- java/awt/EventQueue.java 27 Mar 2007 09:34:50 -0000 1.33
+++ java/awt/EventQueue.java 4 Apr 2007 10:15:15 -0000 1.34
@@ -36,31 +36,30 @@
exception statement from your version. */
package java.awt;
import gnu.java.awt.LowPriorityEvent;
import gnu.java.awt.peer.NativeEventLoopRunningEvent;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.InputMethodEvent;
import java.awt.event.InvocationEvent;
import java.awt.event.PaintEvent;
import java.awt.peer.ComponentPeer;
import java.awt.peer.LightweightPeer;
-import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.util.EmptyStackException;
/* Written using on-line Java 2 Platform Standard Edition v1.3 API
* Specification, as well as "The Java Class Libraries", 2nd edition
* (Addison-Wesley, 1998).
* Status: Believed complete, but untested.
*/
/**
* This class manages a queue of <code>AWTEvent</code> objects that
* are posted to it. The AWT system uses only one event queue for all
* events.
*
* @author Bryce McKinlay
@@ -117,39 +116,32 @@
private EventDispatchThread dispatchThread = new EventDispatchThread(this);
private boolean nativeLoopRunning = false;
private boolean isShutdown ()
{
// This is the exact self-shutdown condition specified in J2SE:
// http://java.sun.com/j2se/1.4.2/docs/api/java/awt/doc-files/AWTThreadIssues.html
if (nativeLoopRunning)
return false;
if (peekEvent() != null)
return false;
- synchronized (Frame.weakFrames)
- {
- for (WeakReference<Frame> r : Frame.weakFrames)
- {
- Frame f = (Frame) r.get();
- if (f != null && f.isDisplayable())
- return false;
- }
- }
+ if (Frame.hasDisplayableFrames())
+ return false;
return true;
}
/**
* Initializes a new instance of <code>EventQueue</code>.
*/
public EventQueue()
{
queues = new Queue[2];
queues[NORM_PRIORITY] = new Queue();
queues[LOW_PRIORITY] = new Queue();
}
/**