Skip to main content

Swing in a better world: Static fields vs AppContext

Posted by alexfromsun on February 9, 2012 at 1:59 AM PST

The problems that are related to the application context might be invisible from the outside of the Swing core libraries, but it has been a big deal for the Swing toolkit developers. Every time when you create a mutable static field in a Swing class you potentially introduce a security whole. It is quite surprising that an ordinary pattern of the Java language becomes a problem. To understand what is going there let's look at what is the application context is.

A Swing application is not necessarily run by its own Java Virtual Machine. Applets or webstart applicatoins placed on the same html page may share one JVM, which leads to the common static data. A static field changed by one application may unexpectedly affect another application.

If we stored the instance of the current LookAndFeel in a static field, setting it in one application would result in changing the LookAndFeel for all the applications within one JVM.

To isolate a Swing application from the other applications within the one JVM we create the Applicatoin Context class which is mostly used as a mutable static map.

Since the usual getter/setter pattern is not valid for the static data in core Swing classes, here is the code snippet from the PopupFactory class, which illustrates the usage of the application context:

public final class SwingStaticProperty {
    private final Map valueMap = new WeakHashMap();

    public SwingStaticProperty() {
    }

    public SwingStaticProperty(V value) {
        set(value);
    }

    public synchronized void set(V value) {
        valueMap.put(Thread.currentThread().getThreadGroup(), value);
    }

    public synchronized V get() {
        return valueMap.get(Thread.currentThread().getThreadGroup());
    }

This pattern is widely used across the Swing classes, for example you can also find it in the UIManager or RepaintManager classes.

AppContext implementation

Internally the application contexts are identified by the thread group of the calling thread. All the system threads belongs to the main thread group, so if you put a value with AppContext.getAppContext().put(); on a main thread you can read it with AppContext.getAppContext().get() on the Event Dispatching Thread.

It is easy to write your own implementation of a static value which safely separates it across different "applicatoin contexts" (unless you use it on a custom threads with a specific thread group)
 

public final class SwingStaticProperty {
    private final Map valueMap = new WeakHashMap();

    public SwingStaticProperty() {
    }

    public SwingStaticProperty(V value) {
        set(value);
    }

    public synchronized void set(V value) {
        valueMap.put(Thread.currentThread().getThreadGroup(), value);
    }

    public synchronized V get() {
        return valueMap.get(Thread.currentThread().getThreadGroup());
    }

Existing drawbacks

  • The AppContext class belongs to the sun.awt package which means that it is not a part of the open API.
  • AppContext implementation is based on the undocumented features
  • Local suppression of a widely known pattern leads to multiple bugs of the same kind

Eventually we have fixed all known bugs which are related to the described problem.
Anyway it was interesting to remember some details about it.

This was an entry from the Swing in a better world series

Thanks
alexp

Related Topics >>