1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
|
/**
* License unknown.
* based on Alexander Potochkin's "Debugging Swing, the final summary"
* when oracle acquired sun, this blog post was removed, and lives only in copies.
* most complex was found:
http://web.archive.org/web/20150523152453/https://weblogs.java.net/blog/alexfromsun/archive/2006/02/debugging_swing.html
*/
package net.sourceforge.swing;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import javax.swing.JComponent;
import javax.swing.RepaintManager;
import static net.sourceforge.swing.SwingUtils.trace;
/**
* For usage of this class, please refer to http://weblogs.java.net/blog/alexfromsun/archive/2006/02/debugging_swing.html
* <p> To use it, call RepaintManager.setCurrentManager(new ThreadCheckingRepaintManager()) then watch the print out
* from the console of all threading violations. </p>
*/
public final class ThreadCheckingRepaintManager extends RepaintManager {
// it is recommended to pass the complete check
private boolean completeCheck = true;
private boolean checkIsShowing = false;
/**
* Creates ThreadCheckingRepaintManager. You can create one and set it using RepaintManager.setCurrentManager(new
* ThreadCheckingRepaintManager()).
*/
public ThreadCheckingRepaintManager() {
super();
}
/**
* Creates ThreadCheckingRepaintManager. You can create one and set it using RepaintManager.setCurrentManager(new
* ThreadCheckingRepaintManager()).
*
* @param checkIsShowing true to only check showing components.
*/
public ThreadCheckingRepaintManager(boolean checkIsShowing) {
super();
this.checkIsShowing = checkIsShowing;
}
/**
* Initially there was a rule that it is safe to create and use Swing components until they are realized but this
* rule is not valid any more, and now it is recommended to interact with Swing from EDT only.
*
* That's why completeCheck flag is used - if you test the old program switch it to false, but new applications
* should be tested with completeCheck set to true*
*
* @return true or false. By default, it is false.
*/
public boolean isCompleteCheck() {
return completeCheck;
}
/**
* @param completeCheck true or false.
*
* @see #isCompleteCheck()
*/
public void setCompleteCheck(boolean completeCheck) {
this.completeCheck = completeCheck;
}
@Override
public synchronized void addInvalidComponent(JComponent jComponent) {
checkThreadViolations(jComponent);
super.addInvalidComponent(jComponent);
}
@Override
public synchronized void addDirtyRegion(JComponent jComponent, int i, int i1, int i2, int i3) {
checkThreadViolations(jComponent);
super.addDirtyRegion(jComponent, i, i1, i2, i3);
}
private void checkThreadViolations(JComponent c) {
if (!SwingUtils.isEventDispatchThread() && (completeCheck || checkIsShowing(c))) {
Exception exception = new Exception();
boolean repaint = false;
boolean fromSwing = false;
StackTraceElement[] stackTrace = exception.getStackTrace();
for (StackTraceElement st : stackTrace) {
if (repaint && st.getClassName().startsWith("javax.swing.")) {
fromSwing = true;
}
if ("repaint".equals(st.getMethodName())) {
repaint = true;
}
}
if (repaint && !fromSwing) {
//no problems here, since repaint() is thread safe
return;
}
trace("----------Wrong Thread START");
trace(getStrackTraceAsString(exception));
trace("----------Wrong Thread END");
}
}
@SuppressWarnings({"SimplifiableIfStatement"})
private boolean checkIsShowing(JComponent c) {
if (this.checkIsShowing) {
return c.isShowing();
} else {
return true;
}
}
private String getStrackTraceAsString(Exception e) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
PrintStream printStream = new PrintStream(byteArrayOutputStream);
e.printStackTrace(printStream);
printStream.flush();
return byteArrayOutputStream.toString();
}
}
|