synchronized (table) { this.table.clear(); // Clear out the Hashtable to ease garbage collection } numAppContexts--; mostRecentKeyValue = null; } static final class PostShutdownEventRunnable implements Runnable { private final AppContext appContext; public PostShutdownEventRunnable(AppContext ac) { appContext = ac; } public void run() { final EventQueue eq = (EventQueue)appContext.get(EVENT_QUEUE_KEY); if (eq != null) { eq.postEvent(AWTAutoShutdown.getShutdownEvent()); } } } static final class CreateThreadAction implements PrivilegedAction { private final AppContext appContext; private final Runnable runnable; public CreateThreadAction(AppContext ac, Runnable r) { appContext = ac; runnable = r; } public Object run() { Thread t = new Thread(appContext.getThreadGroup(), runnable); t.setContextClassLoader(appContext.getContextClassLoader()); t.setPriority(Thread.NORM_PRIORITY + 1); t.setDaemon(true); return t; } } static void stopEventDispatchThreads() { for (AppContext appContext: getAppContexts()) { if (appContext.isDisposed()) { continue; } Runnable r = new PostShutdownEventRunnable(appContext); // For security reasons EventQueue.postEvent should only be called // on a thread that belongs to the corresponding thread group. if (appContext != AppContext.getAppContext()) { // Create a thread that belongs to the thread group associated // with the AppContext and invokes EventQueue.postEvent. PrivilegedAction action = new CreateThreadAction(appContext, r); Thread thread = (Thread)AccessController.doPrivileged(action); thread.start(); } else { r.run(); } } } private MostRecentKeyValue mostRecentKeyValue = null; private MostRecentKeyValue shadowMostRecentKeyValue = null; /** * Returns the value to which the specified key is mapped in this context. * * @param key a key in the AppContext. * @return the value to which the key is mapped in this AppContext; * <code>null</code> if the key is not mapped to any value. * @see #put(Object, Object) * @since 1.2 */ public Object get(Object key) { /* * The most recent reference should be updated inside a synchronized * block to avoid a race when put() and get() are executed in * parallel on different threads. */ synchronized (table) { // Note: this most recent key/value caching is thread-hot. // A simple test using SwingSet found that 72% of lookups // were matched using the most recent key/value. By instantiating // a simple MostRecentKeyValue object on cache misses, the // cache hits can be processed without synchronization. MostRecentKeyValue recent = mostRecentKeyValue; if ((recent != null) && (recent.key == key)) { return recent.value; } Object value = table.get(key); if(mostRecentKeyValue == null) { mostRecentKeyValue = new MostRecentKeyValue(key, value); shadowMostRecentKeyValue = new MostRecentKeyValue(key, value); } else { MostRecentKeyValue auxKeyValue = mostRecentKeyValue; shadowMostRecentKeyValue.setPair(key, value); mostRecentKeyValue = shadowMostRecentKeyValue; shadowMostRecentKeyValue = auxKeyValue; } return value; } } /** * Maps the specified <code>key</code> to the specified * <code>value</code> in this AppContext. Neither the key nor the * value can be <code>null</code>. * <p> * The value can be retrieved by calling the <code>get</code> method * with a key that is equal to the original key. * * @param key the AppContext key. * @param value the value. * @return the previous value of the specified key in this * AppContext, or <code>null</code> if it did not have one. * @exception NullPointerException if the key or value is * <code>null</code>. * @see #get(Object) * @since 1.2 */ public Object put(Object key, Object value) { synchronized (table) { MostRecentKeyValue recent = mostRecentKeyValue; if ((recent != null) && (recent.key == key)) recent.value = value; return table.put(key, value); } } /** * Removes the key (and its corresponding value) from this * AppContext. This method does nothing if the key is not in the * AppContext. * * @param key the key that needs to be removed. * @return the value to which the key had been mapped in this AppContext, * or <code>null</code> if the key did not have a mapping. * @since 1.2 */ public Object remove(Object key) { synchronized (table) { MostRecentKeyValue recent = mostRecentKeyValue; if ((recent != null) && (recent.key == key)) recent.value = null; return table.remove(key); } } /** * Returns the root ThreadGroup for all Threads contained within * this AppContext. * @since 1.2 */ public ThreadGroup getThreadGroup() { return threadGroup; } /** * Returns the context ClassLoader that was used to create this * AppContext. * * @see java.lang.Thread#getContextClassLoader */ public ClassLoader getContextClassLoader() { return contextClassLoader; } /** * Returns a string representation of this AppContext. * @since 1.2 */ @Override public String toString() { return getClass().getName() + "[threadGroup=" + threadGroup.getName() + "]"; } /** * Returns an array of all the property change listeners * registered on this component. * * @return all of this component's <code>PropertyChangeListener</code>s * or an empty array if no property change * listeners are currently registered * * @see #addPropertyChangeListener * @see #removePropertyChangeListener * @see #getPropertyChangeListeners(java.lang.String) * @see java.beans.PropertyChangeSupport#getPropertyChangeListeners * @since 1.4 */ public synchronized PropertyChangeListener[] getPropertyChangeListeners() { if (changeSupport == null) { return new PropertyChangeListener[0]; } return changeSupport.getPropertyChangeListeners(); } /** * Adds a PropertyChangeListener to the listener list for a specific * property. The specified property may be one of the following: * <ul> * <li>if this AppContext is disposed ("disposed")</li> * </ul> * <ul> * <li>if this AppContext's unowned Windows have been disposed * ("guidisposed"). Code to cleanup after the GUI is disposed * (such as LookAndFeel.uninitialize()) should execute in response to * this property being fired. Notifications for the "guidisposed" * property are sent on the event dispatch thread.</li> * </ul> * <p> * If listener is null, no exception is thrown and no action is performed. * * @param propertyName one of the property names listed above * @param listener the PropertyChangeListener to be added * * @see #removePropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener) * @see #getPropertyChangeListeners(java.lang.String) * @see #addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener) */ public synchronized void addPropertyChangeListener( String propertyName, PropertyChangeListener listener) { if (listener == null) { return; } if (changeSupport == null) { changeSupport = new PropertyChangeSupport(this); } changeSupport.addPropertyChangeListener(propertyName, listener); } /** * Removes a PropertyChangeListener from the listener list for a specific * property. This method should be used to remove PropertyChangeListeners * that were registered for a specific bound property. * <p> * If listener is null, no exception is thrown and no action is performed. * * @param propertyName a valid property name * @param listener the PropertyChangeListener to be removed * * @see #addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener) * @see #getPropertyChangeListeners(java.lang.String) * @see #removePropertyChangeListener(java.beans.PropertyChangeListener) */ public synchronized void removePropertyChangeListener( String propertyName, PropertyChangeListener listener) { if (listener == null || changeSupport == null) { return; } changeSupport.removePropertyChangeListener(propertyName, listener); } /** * Returns an array of all the listeners which have been associated * with the named property. * * @return all of the <code>PropertyChangeListeners</code> associated with * the named property or an empty array if no listeners have * been added * * @see #addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener) * @see #removePropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener) * @see #getPropertyChangeListeners * @since 1.4 */ public synchronized PropertyChangeListener[] getPropertyChangeListeners( String propertyName) { if (changeSupport == null) { return new PropertyChangeListener[0]; } return changeSupport.getPropertyChangeListeners(propertyName); }} final class MostRecentKeyValue { Object key; Object value; MostRecentKeyValue(Object k, Object v) { key = k; value = v; } void setPair(Object k, Object v) { key = k; value = v; }}Lines 501–793 of 793. Previous lines
synchronized (table) { this.table.clear(); // Clear out the Hashtable to ease garbage collection } numAppContexts--; mostRecentKeyValue = null; } static final class PostShutdownEventRunnable implements Runnable { private final AppContext appContext; public PostShutdownEventRunnable(AppContext ac) { appContext = ac; } public void run() { final EventQueue eq = (EventQueue)appContext.get(EVENT_QUEUE_KEY); if (eq != null) { eq.postEvent(AWTAutoShutdown.getShutdownEvent()); } } } static final class CreateThreadAction implements PrivilegedAction { private final AppContext appContext; private final Runnable runnable; public CreateThreadAction(AppContext ac, Runnable r) { appContext = ac; runnable = r; } public Object run() { Thread t = new Thread(appContext.getThreadGroup(), runnable); t.setContextClassLoader(appContext.getContextClassLoader()); t.setPriority(Thread.NORM_PRIORITY + 1); t.setDaemon(true); return t; } } static void stopEventDispatchThreads() { for (AppContext appContext: getAppContexts()) { if (appContext.isDisposed()) { continue; } Runnable r = new PostShutdownEventRunnable(appContext); // For security reasons EventQueue.postEvent should only be called // on a thread that belongs to the corresponding thread group. if (appContext != AppContext.getAppContext()) { // Create a thread that belongs to the thread group associated // with the AppContext and invokes EventQueue.postEvent. PrivilegedAction action = new CreateThreadAction(appContext, r); Thread thread = (Thread)AccessController.doPrivileged(action); thread.start(); } else { r.run(); } } } private MostRecentKeyValue mostRecentKeyValue = null; private MostRecentKeyValue shadowMostRecentKeyValue = null; /** * Returns the value to which the specified key is mapped in this context. * * @param key a key in the AppContext. * @return the value to which the key is mapped in this AppContext; * <code>null</code> if the key is not mapped to any value. * @see #put(Object, Object) * @since 1.2 */ public Object get(Object key) { /* * The most recent reference should be updated inside a synchronized * block to avoid a race when put() and get() are executed in * parallel on different threads. */ synchronized (table) { // Note: this most recent key/value caching is thread-hot. // A simple test using SwingSet found that 72% of lookups // were matched using the most recent key/value. By instantiating // a simple MostRecentKeyValue object on cache misses, the // cache hits can be processed without synchronization. MostRecentKeyValue recent = mostRecentKeyValue; if ((recent != null) && (recent.key == key)) { return recent.value; } Object value = table.get(key); if(mostRecentKeyValue == null) { mostRecentKeyValue = new MostRecentKeyValue(key, value); shadowMostRecentKeyValue = new MostRecentKeyValue(key, value); } else { MostRecentKeyValue auxKeyValue = mostRecentKeyValue; shadowMostRecentKeyValue.setPair(key, value); mostRecentKeyValue = shadowMostRecentKeyValue; shadowMostRecentKeyValue = auxKeyValue; } return value; } } /** * Maps the specified <code>key</code> to the specified * <code>value</code> in this AppContext. Neither the key nor the * value can be <code>null</code>. * <p> * The value can be retrieved by calling the <code>get</code> method * with a key that is equal to the original key. * * @param key the AppContext key. * @param value the value. * @return the previous value of the specified key in this * AppContext, or <code>null</code> if it did not have one. * @exception NullPointerException if the key or value is * <code>null</code>. * @see #get(Object) * @since 1.2 */ public Object put(Object key, Object value) { synchronized (table) { MostRecentKeyValue recent = mostRecentKeyValue; if ((recent != null) && (recent.key == key)) recent.value = value; return table.put(key, value); } } /** * Removes the key (and its corresponding value) from this * AppContext. This method does nothing if the key is not in the * AppContext. * * @param key the key that needs to be removed. * @return the value to which the key had been mapped in this AppContext, * or <code>null</code> if the key did not have a mapping. * @since 1.2 */ public Object remove(Object key) { synchronized (table) { MostRecentKeyValue recent = mostRecentKeyValue; if ((recent != null) && (recent.key == key)) recent.value = null; return table.remove(key); } } /** * Returns the root ThreadGroup for all Threads contained within * this AppContext. * @since 1.2 */ public ThreadGroup getThreadGroup() { return threadGroup; } /** * Returns the context ClassLoader that was used to create this * AppContext. * * @see java.lang.Thread#getContextClassLoader */ public ClassLoader getContextClassLoader() { return contextClassLoader; } /** * Returns a string representation of this AppContext. * @since 1.2 */ @Override public String toString() { return getClass().getName() + "[threadGroup=" + threadGroup.getName() + "]"; } /** * Returns an array of all the property change listeners * registered on this component. * * @return all of this component's <code>PropertyChangeListener</code>s * or an empty array if no property change * listeners are currently registered * * @see #addPropertyChangeListener * @see #removePropertyChangeListener * @see #getPropertyChangeListeners(java.lang.String) * @see java.beans.PropertyChangeSupport#getPropertyChangeListeners * @since 1.4 */ public synchronized PropertyChangeListener[] getPropertyChangeListeners() { if (changeSupport == null) { return new PropertyChangeListener[0]; } return changeSupport.getPropertyChangeListeners(); } /** * Adds a PropertyChangeListener to the listener list for a specific * property. The specified property may be one of the following: * <ul> * <li>if this AppContext is disposed ("disposed")</li> * </ul> * <ul> * <li>if this AppContext's unowned Windows have been disposed * ("guidisposed"). Code to cleanup after the GUI is disposed * (such as LookAndFeel.uninitialize()) should execute in response to * this property being fired. Notifications for the "guidisposed" * property are sent on the event dispatch thread.</li> * </ul> * <p> * If listener is null, no exception is thrown and no action is performed. * * @param propertyName one of the property names listed above * @param listener the PropertyChangeListener to be added * * @see #removePropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener) * @see #getPropertyChangeListeners(java.lang.String) * @see #addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener) */ public synchronized void addPropertyChangeListener( String propertyName, PropertyChangeListener listener) { if (listener == null) { return; } if (changeSupport == null) { changeSupport = new PropertyChangeSupport(this); } changeSupport.addPropertyChangeListener(propertyName, listener); } /** * Removes a PropertyChangeListener from the listener list for a specific * property. This method should be used to remove PropertyChangeListeners * that were registered for a specific bound property. * <p> * If listener is null, no exception is thrown and no action is performed. * * @param propertyName a valid property name * @param listener the PropertyChangeListener to be removed * * @see #addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener) * @see #getPropertyChangeListeners(java.lang.String) * @see #removePropertyChangeListener(java.beans.PropertyChangeListener) */ public synchronized void removePropertyChangeListener( String propertyName, PropertyChangeListener listener) { if (listener == null || changeSupport == null) { return; } changeSupport.removePropertyChangeListener(propertyName, listener); } /** * Returns an array of all the listeners which have been associated * with the named property. * * @return all of the <code>PropertyChangeListeners</code> associated with * the named property or an empty array if no listeners have * been added * * @see #addPropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener) * @see #removePropertyChangeListener(java.lang.String, java.beans.PropertyChangeListener) * @see #getPropertyChangeListeners * @since 1.4 */ public synchronized PropertyChangeListener[] getPropertyChangeListeners( String propertyName) { if (changeSupport == null) { return new PropertyChangeListener[0]; } return changeSupport.getPropertyChangeListeners(propertyName); } } final class MostRecentKeyValue { Object key; Object value; MostRecentKeyValue(Object k, Object v) { key = k; value = v; } void setPair(Object k, Object v) { key = k; value = v; } }