非同期コードをデバッグする
非同期コードのデバッグは、タスクが 1 つのスレッドでスケジュールされ、別のスレッドで実行されることが多いため、困難です。 各スレッドには独自のスタックトレースが存在するため、スレッドの開始前に何が起こったかを把握することが困難です。
IntelliJ IDEA は、異なるスレッドのフレーム間の接続を確立することにより、それを容易にします。 これにより、ワーカースレッドからタスクがスケジュールされた場所までさかのぼって、実行がすべて同じスレッド内にあるかのようにプログラムをデバッグできます。
非同期スタックトレースを試すには、次の例をデバッグします。
printNum() メソッドのブレークポイントで停止すると、2 つのスタックトレースが利用できます。
現在のスレッド (ワーカー)
メインスレッド (タスクがスケジュールされた場所)

コンソールの非同期スタックトレース
デフォルトでは、コードをデバッグしたり、 JUnit/TestNG ユニットテストを実行したりすると、非同期スタックトレースがコンソールに表示されます。

対応する実行構成で 例外の非同期スタックトレースを印刷する チェックボックスをオフにすると、テストの非同期スタックトレースを無効にすることができます。

デバッグセッションの非同期スタックトレースをオンまたはオフにするには、 の インストゥルメントエージェント オプションを使用します。
非同期アノテーション
非同期スタックトレースは、Swing および Java Concurrency API ですぐに使用できますが、独自のカスタムクラスで使用できるように手動で拡張することもできます。 これは、特別なアノテーションを使用して行われます。
アノテーションは、キャプチャーポイントと挿入ポイントを定義するために使用されます。
キャプチャーポイントは、スタックトレースがキャプチャーされる方法です。 キャプチャーポイントでは、スタックトレースが保存され、キーが割り当てられます。 キャプチャーポイントには
@Async.Scheduleアノテーションが付けられています。挿入ポイントは、以前に保存されたスタックトレースの 1 つが現在のスタックにアタッチされるメソッドです。 挿入ポイントには、
@Async.Executeアノテーションが付けられます。キーは、キャプチャーされたスタックトレースの一意の識別子として機能するパラメーターまたはオブジェクト参照です。 Async スタックトレースの各部分を一致させるために必要です。
キャプチャーポイントと挿入ポイントを定義する
メソッドまたはそのパラメーターにアノテーションを付けることができます。
オブジェクト参照 (
this) をキーとして使用する場合は、メソッド自体にアノテーションを付けます。例:@Async.Schedule private static void schedule(Integer i) { System.out.println("Scheduling " + i); queue.put(i); }パラメーター値をキーとして使用する場合は、メソッドパラメーターにアノテーションを付けます。例:
private static void schedule(@Async.Schedule Integer i) { System.out.println("Scheduling " + i); queue.put(i); }
アノテーションがどのように機能するかをテストするには、次の例を使用できます。
カスタムアノテーションを定義する
プロジェクトに JetBrains アノテーションの依存関係を追加したくない場合は、独自のアノテーションを定義して、デフォルトのアノテーションの代わりに使用することができます。
キャプチャーポイントと挿入ポイントに独自のアノテーションを作成します。 参考として、 Async.java(英語) を参照してください。
Ctrl+Alt+S を押して設定を開き、 を選択します。
アノテーションの構成 をクリックします。
非同期アノテーションの構成 ダイアログで、
をクリックして、カスタムアノテーションを 非同期スケジュールアノテーション および 非同期アノテーションを実行する に追加します。
リモート JVM で非同期スタックトレースを表示する
たとえば、 Docker コンテナー内で管理されているリモートプロセスをデバッグしている場合でも、JVM インストルメンティングエージェントを使用して、IDE から開始されたかのように非同期スタックトレースを表示できます。
リモートでエージェントを使用するには、次の手順を実行します。
<IDEA インストールフォルダー> /lib/rt/debugger-agent.jar をリモートマシン上の任意の場所にコピーします
-javaagent:<path to debugger-agent.jar>をリモート JVM オプションに追加する
Async スタックトレースのオーバーヘッド
場合によっては、Async スタックトレースが目に見えるオーバーヘッドを引き起こすことがあります。 Async スタックが長くなりすぎる場合、たとえば多数の CompletableFuture コールバックやコルーチンの継続などでこのようなことが起こります。
この場合、IntelliJ IDEA はスロットリングを適用し、パフォーマンスが通常であるときのみ Async スタックトレースを収集します。 スロットリングにより収集されなかった Async スタックトレースは、 フレーム タブの 取得できませんでした でマークされます。 この動作は で制御できます。
デバッガーのオーバーヘッドの測定および管理については、 デバッガーのオーバーヘッドを監視する を参照してください。