One approach is to install a custom redraw manager that detects and registers when drawing is performed in a thread other than EDT. We use this approach in our project, adapted from the following blog: http://weblogs.java.net/blog/alexfromsun/archive/2006/02/debugging_swing.html . This will not detect all classes of EDT flow violations, but it is definitely much better than nothing.
Update:
As the commentator noted, the linked web page is no longer available. Here is my code adapted from the blog:
import javax.swing.JComponent; import javax.swing.RepaintManager; import javax.swing.SwingUtilities; import org.apache.log4j.Logger; import sun.awt.AppContext; public class DetectEdtViolationRepaintManager extends RepaintManager { private static final Logger LOGGER = Logger.getLogger( DetectEdtViolationRepaintManager.class); private ThreadLocal alreadyWarnedLocal; public static void install() { install(false); } public static void install(boolean warnRepeatedly) { AppContext.getAppContext().put(RepaintManager.class, new DetectEdtViolationRepaintManager(warnRepeatedly)); LOGGER.info("Installed new DetectEdtViolationRepaintManager"); } private DetectEdtViolationRepaintManager(boolean warnRepeatedly) { if (!warnRepeatedly) { this.alreadyWarnedLocal = new ThreadLocal(); } } public synchronized void addInvalidComponent(JComponent component) { checkThreadViolations(); super.addInvalidComponent(component); } public synchronized void addDirtyRegion(JComponent component, int x, int y, int w, int h) { checkThreadViolations(); super.addDirtyRegion(component, x, y, w, h); } private void checkThreadViolations() { if (alreadyWarnedLocal != null && Boolean.TRUE.equals(alreadyWarnedLocal.get())) { return; } if (!SwingUtilities.isEventDispatchThread()) { if (alreadyWarnedLocal != null) { alreadyWarnedLocal.set(Boolean.TRUE); } LOGGER.warn("painting on non-EDT thread", new Exception()); } } }
source share