boolean (@Nullable Component c, StackTraceElement[] stackTrace) { boolean repaint = false; boolean fromSwing = false; boolean swingKnownNonAwtOperations = false; for (StackTraceElement st : stackTrace) { String className = st.getClassName(); String methodName = st.getMethodName(); if (repaint && className.startsWith("javax.swing.")) { fromSwing = true; } if (repaint && "imageUpdate".equals(methodName)) { swingKnownNonAwtOperations = true; } if ("read".equals(methodName) && className.startsWith("javax.swing.JEditorPane") || "setCharacterAttributes".equals(methodName) && className.startsWith("javax.swing.text.DefaultStyledDocument")) { swingKnownNonAwtOperations = true; break; } if ("repaint".equals(methodName)) { repaint = true; fromSwing = false; } } if (swingKnownNonAwtOperations) { return true; } if (repaint && !fromSwing) { //no problems here, since repaint() is thread safe return true; } //ignore the last processed component if (SoftReference.dereference(myLastComponent) == c) { return true; } myLastComponent = new WeakReference<>(c); return false; }