/**
   * Disposes of this AppContext, all of its top-level Frames, and all Threads and ThreadGroups
   * contained within it.
   *
   * <p>This method must be called from a Thread which is not contained within this AppContext.
   *
   * @exception IllegalThreadStateException if the current thread is contained within this
   *     AppContext
   * @since JDK1.2
   */
  public void dispose() throws IllegalThreadStateException {
    // Check to be sure that the current Thread isn't in this AppContext
    if (this.threadGroup.parentOf(Thread.currentThread().getThreadGroup())) {
      throw new IllegalThreadStateException(
          "Current Thread is contained within AppContext to be disposed.");
    }

    synchronized (this) {
      if (this.isDisposed) {
        return; // If already disposed, bail.
      }
      this.isDisposed = true;
    }

    // final PropertyChangeSupport changeSupport = this.changeSupport;
    // if (changeSupport != null) {
    //    changeSupport.firePropertyChange(DISPOSED_PROPERTY_NAME, false, true);
    // }

    // First, we post an InvocationEvent to be run on the
    // EventDispatchThread which disposes of all top-level Frames

    final Object notificationLock = new Object();

    /*no mutiple frames in basis
     * Runnable runnable = new Runnable() { public void run() {
     *     Frame [] frames = Frame.getFrames();
     *     for (int i = frames.length - 1; i >= 0; i--) {
     *         frames[i].dispose(); // Dispose of all top-level Frames
     *     }
     *     synchronized(notificationLock) {
     *         notificationLock.notifyAll(); // Notify caller that we're done
     *     }
     * } };
     * synchronized(notificationLock) {
     *     SunToolkit.postEvent(this,
     *         new InvocationEvent(Toolkit.getDefaultToolkit(), runnable));
     *     try {
     *         notificationLock.wait(DISPOSAL_TIMEOUT);
     *     } catch (InterruptedException e) { }
     *  }
     */

    // Next, we post another InvocationEvent to the end of the
    // EventQueue.  When it's executed, we know we've executed all
    // events in the queue.

    Runnable runnable =
        new Runnable() {
          public void run() {
            synchronized (notificationLock) {
              notificationLock.notifyAll(); // Notify caller that we're done
            }
          }
        };
    synchronized (notificationLock) {
      SunToolkit.postEvent(this, new InvocationEvent(Toolkit.getDefaultToolkit(), runnable));
      try {
        notificationLock.wait(DISPOSAL_TIMEOUT);
      } catch (InterruptedException e) {
      }
    }

    // Next, we interrupt all Threads in the ThreadGroup
    this.threadGroup.interrupt();
    // Note, the EventDispatchThread we've interrupted may dump an
    // InterruptedException to the console here.  This needs to be
    // fixed in the EventDispatchThread, not here.

    // Next, we sleep 10ms at a time, waiting for all of the active
    // Threads in the ThreadGroup to exit.

    long startTime = System.currentTimeMillis();
    long endTime = startTime + (long) THREAD_INTERRUPT_TIMEOUT;
    while ((this.threadGroup.activeCount() > 0) && (System.currentTimeMillis() < endTime)) {
      try {
        Thread.sleep(10);
      } catch (InterruptedException e) {
      }
    }

    // Then, we stop any remaining Threads
    // this.threadGroup.stop();

    // Next, we sleep 10ms at a time, waiting for all of the active
    // Threads in the ThreadGroup to die.

    startTime = System.currentTimeMillis();
    endTime = startTime + (long) THREAD_INTERRUPT_TIMEOUT;
    while ((this.threadGroup.activeCount() > 0) && (System.currentTimeMillis() < endTime)) {
      try {
        Thread.sleep(10);
      } catch (InterruptedException e) {
      }
    }

    // Next, we remove this and all subThreadGroups from threadGroup2appContext
    int numSubGroups = this.threadGroup.activeGroupCount();
    if (numSubGroups > 0) {
      ThreadGroup[] subGroups = new ThreadGroup[numSubGroups];
      numSubGroups = this.threadGroup.enumerate(subGroups);
      for (int subGroup = 0; subGroup < numSubGroups; subGroup++) {
        threadGroup2appContext.remove(subGroups[subGroup]);
      }
    }
    threadGroup2appContext.remove(this.threadGroup);

    MostRecentThreadAppContext recent = mostRecentThreadAppContext;
    if ((recent != null) && (recent.appContext == this)) mostRecentThreadAppContext = null;
    // If the "most recent" points to this, clear it for GC

    // Finally, we destroy the ThreadGroup entirely.
    try {
      this.threadGroup.destroy();
    } catch (IllegalThreadStateException e) {
      // Fired if not all the Threads died, ignore it and proceed
    }

    synchronized (table) {
      this.table.clear(); // Clear out the Hashtable to ease garbage collection
    }

    numAppContexts--;

    mostRecentKeyValue = null;
  }
Beispiel #2
0
  /**
   * Disposes of this AppContext, all of its top-level Frames, and all Threads and ThreadGroups
   * contained within it.
   *
   * <p>This method must be called from a Thread which is not contained within this AppContext.
   *
   * @exception IllegalThreadStateException if the current thread is contained within this
   *     AppContext
   * @since 1.2
   */
  public void dispose() throws IllegalThreadStateException {
    // Check to be sure that the current Thread isn't in this AppContext
    if (this.threadGroup.parentOf(Thread.currentThread().getThreadGroup())) {
      throw new IllegalThreadStateException(
          "Current Thread is contained within AppContext to be disposed.");
    }

    synchronized (this) {
      if (this.isDisposed) {
        return; // If already disposed, bail.
      }
      this.isDisposed = true;
    }

    final PropertyChangeSupport changeSupport = this.changeSupport;
    if (changeSupport != null) {
      changeSupport.firePropertyChange(DISPOSED_PROPERTY_NAME, false, true);
    }

    // First, we post an InvocationEvent to be run on the
    // EventDispatchThread which disposes of all top-level Frames and TrayIcons

    final Object notificationLock = new Object();

    Runnable runnable =
        new Runnable() {
          public void run() {
            Window[] windowsToDispose = Window.getOwnerlessWindows();
            for (Window w : windowsToDispose) {
              w.dispose();
            }
            AccessController.doPrivileged(
                new PrivilegedAction() {
                  public Object run() {
                    if (!GraphicsEnvironment.isHeadless() && SystemTray.isSupported()) {
                      SystemTray systemTray = SystemTray.getSystemTray();
                      TrayIcon[] trayIconsToDispose = systemTray.getTrayIcons();
                      for (TrayIcon ti : trayIconsToDispose) {
                        systemTray.remove(ti);
                      }
                    }
                    return null;
                  }
                });
            // Alert PropertyChangeListeners that the GUI has been disposed.
            if (changeSupport != null) {
              changeSupport.firePropertyChange(GUI_DISPOSED, false, true);
            }
            synchronized (notificationLock) {
              notificationLock.notifyAll(); // Notify caller that we're done
            }
          }
        };
    synchronized (notificationLock) {
      SunToolkit.postEvent(this, new InvocationEvent(Toolkit.getDefaultToolkit(), runnable));
      try {
        notificationLock.wait(DISPOSAL_TIMEOUT);
      } catch (InterruptedException e) {
      }
    }

    // Next, we post another InvocationEvent to the end of the
    // EventQueue.  When it's executed, we know we've executed all
    // events in the queue.

    runnable =
        new Runnable() {
          public void run() {
            synchronized (notificationLock) {
              notificationLock.notifyAll(); // Notify caller that we're done
            }
          }
        };
    synchronized (notificationLock) {
      SunToolkit.postEvent(this, new InvocationEvent(Toolkit.getDefaultToolkit(), runnable));
      try {
        notificationLock.wait(DISPOSAL_TIMEOUT);
      } catch (InterruptedException e) {
      }
    }
    /* jnode
            // Next, we interrupt all Threads in the ThreadGroup
            this.threadGroup.interrupt();
                // Note, the EventDispatchThread we've interrupted may dump an
                // InterruptedException to the console here.  This needs to be
                // fixed in the EventDispatchThread, not here.

            // Next, we sleep 10ms at a time, waiting for all of the active
            // Threads in the ThreadGroup to exit.

            long startTime = System.currentTimeMillis();
            long endTime = startTime + (long)THREAD_INTERRUPT_TIMEOUT;
            while ((this.threadGroup.activeCount() > 0) &&
                   (System.currentTimeMillis() < endTime)) {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) { }
            }

            // Then, we stop any remaining Threads
            this.threadGroup.stop();

            // Next, we sleep 10ms at a time, waiting for all of the active
            // Threads in the ThreadGroup to die.

            startTime = System.currentTimeMillis();
            endTime = startTime + (long)THREAD_INTERRUPT_TIMEOUT;
            while ((this.threadGroup.activeCount() > 0) &&
                   (System.currentTimeMillis() < endTime)) {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) { }
            }
    jnode*/
    // Next, we remove this and all subThreadGroups from threadGroup2appContext
    int numSubGroups = this.threadGroup.activeGroupCount();
    if (numSubGroups > 0) {
      ThreadGroup[] subGroups = new ThreadGroup[numSubGroups];
      numSubGroups = this.threadGroup.enumerate(subGroups);
      for (int subGroup = 0; subGroup < numSubGroups; subGroup++) {
        threadGroup2appContext.remove(subGroups[subGroup]);
      }
    }
    threadGroup2appContext.remove(this.threadGroup);

    MostRecentThreadAppContext recent = mostRecentThreadAppContext;
    if ((recent != null) && (recent.appContext == this)) mostRecentThreadAppContext = null;
    // If the "most recent" points to this, clear it for GC

    // Finally, we destroy the ThreadGroup entirely.
    try {
      // jnode            this.threadGroup.destroy();
    } catch (IllegalThreadStateException e) {
      // Fired if not all the Threads died, ignore it and proceed
    }

    synchronized (table) {
      this.table.clear(); // Clear out the Hashtable to ease garbage collection
    }

    numAppContexts--;

    mostRecentKeyValue = null;
  }