Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swing verify code on Event Dispatch Thread at runtime

Are there any libraries that instrument code to verify that methods called on Swing components are called on the Event Dispatch Thread? It probably wouldn't be too difficult to write some basic code for doing this, but I'm sure there are edge cases and whatnot that other people have handled. I'm looking for this at runtime though, not for unit tests.

like image 883
Jeff Storey Avatar asked Jun 10 '10 13:06

Jeff Storey


People also ask

What method can you use to know if your code is running inside an event dispatch thread?

If you need to determine whether your code is running on the event dispatch thread, invoke javax. swing. SwingUtilities. isEventDispatchThread .

What do you mean by Swing event dispatching thread in Java Swing?

The event dispatching thread (EDT) is a background thread used in Java to process events from the Abstract Window Toolkit (AWT) graphical user interface event queue.

How do you update Swing component from a thread other than EDT?

You can use invokeAndWait() and invokeLater() to update a Swing component from any arbitrary thread.

Why are swings not thread safe?

Most Swing object methods are not "thread safe". This means that if those (non thread safe) method are invoked from multiple threads this could result in thread interference or memory consistency errors. Only thread safe methods can be safely invoked from any thread.


1 Answers

The FEST framework has a tool to detect Swing usage off the EDT. It's basically a RepaintManager that you install. The framework is oriented towards testing, but the RepaintManager can be used at deployment time.

  • See FEST - Swing's Event Dispatch Thread

Alternatively, to check all methods such as getters and setters for access only on the EDT, you can use AspectJ and load-time weaving to add the SwingUtilities.isDisaptchThread() advice to each method on your swing components (and the JDK Swing components.)

@Aspect
public class EDTCheck {

    @Pointcut("call (* javax.swing..*+.*(..)) || " +
              "call (javax.swing..*+.new(..))")
    public void swingMethods() {}

    @Pointcut("call (* com.mystuff.swing..*+.*(..)) || " +
              "call (com.mystuff.swing..*+.new(..))")
    public void mySwingMethods() {}


    @Pointcut("call (* javax.swing..*+.add*Listener(..)) || " +
              "call (* javax.swing..*+.remove*Listener(..)) || " +
              "call (void javax.swing.JComponent+.setText(java.lang.String))")
    public void safeMethods() {}

    @Before("(swingMethods() || mySwingMethods()) && !safeMethods()")
    public void checkCallingThread(JoinPoint.StaticPart thisJoinPointStatic) {
        if(!SwingUtilities.isDispatchThread()) {
            System.out.println(
                    "Swing single thread rule violation: " 
                    + thisJoinPointStatic);
            Thread.dumpStack();
            // or you might throw an unchecked exception
        }
    }

}

(Slightly modified from the article - added mySwingMethods pointcut, and use SwingUtiliites.isDispatchThread(). In practice it is the same as EventQueue.isDispatchThread() but the abstraction is cleaner.)

  • See Using AspectJ to detect violations of the Swing Single-Thread Rule
like image 157
mdma Avatar answered Sep 21 '22 21:09

mdma