Swingコンポーネントで呼び出されたメソッドがイベントディスパッチスレッドで呼び出されていることを確認するためのコードをインストルメント化するライブラリはありますか?これを行うための基本的なコードを書くのはおそらくそれほど難しいことではありませんが、他の人が扱ったエッジケースなどがあると確信しています。ただし、単体テストではなく、実行時にこれを探しています。
4 に答える
FESTフレームワークには、EDT 以外でのSwing の使用を検出するツールがあります。基本的に、インストールするのは RepaintManager です。フレームワークはテスト向けですが、デプロイ時に RepaintManager を使用できます。
- FEST - Swing のイベント ディスパッチ スレッドを参照してください。
または、getter や setter などのすべてのメソッドが EDT でのみアクセスできるようにチェックするには、AspectJ とロード時のウィービングを使用して、Swing コンポーネント (および JDK Swing コンポーネント) の各メソッドに SwingUtilities.isDisaptchThread() アドバイスを追加します。 )
@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
}
}
}
(記事から少し変更 - mySwingMethods ポイントカットを追加し、SwingUtilites.isDispatchThread() を使用します。実際には、EventQueue.isDispatchThread() と同じですが、抽象化はよりクリーンです。)
コーディングの観点から、EDT コードと非 EDT コードを明確に分離します。SwingWorker
ペストのように避けてください。
EDT を使用していることを表明するには (!
オフの場合は挿入)、次の行を追加します。
assert java.awt.EventQueue.isDispatchThread();
-ea
これを行うには/が必要です-enableassertions
。ただし、ほとんどの場合、実行可能なコメントとして機能します。
http://today.java.net/pub/a/today/2005/04/19/desktoplive.htmlで、Scott Delap による単純で巧妙な (完全な防弾ではありませんが) メソッドを見つけました 。
上記の mdma による FEST の回答で示唆されているように、カスタム RepaintManger を使用できます。メソッドをオーバーライドするだけです。
addInvalidComponent(JComponent component)
と
addDirtyRegion(JComponent component, int x, int y, int w, int h)
と使用
SwingUtilities.isEventDispatchThread()
AWT を使用しているかどうかを確認するには、これを JUnit に簡単に統合できます。
org.JUnit.Assert.fail("AWT Thread Violation")
あなたのチェックルーチンで。
ここでのロジックは、ほとんどの (すべてではない) Swing 操作で再描画が発生し、最終的に RepaintManager でこれらのメソッドが呼び出されるため、これらをキャッチしてチェックできるようになるというものです。
アレクサンダー・ポトキンは、ここでさまざまな方法をまとめています: http://weblogs.java.net/blog/alexfromsun/archive/2006/02/debugging_swing.html
必要なのは次のコードだけです。
void method() {
if (!SwingUtilities.isEventDispatchThread()) {
SwingUtilities.invokeAndWait(new Runnable() { public void run() { method(); } );
return;
}
// do method code here, guaranteed to be in EDT
}
また、Substanceを LAF として使用すると、EDT で Swing 関連のものが実行されていない場所を特定するのに役立ちます。Swing が適切なスレッドで実行されているか、例外で失敗していることを確認するためのチェックが行われています。