IntelliJ IDEA 2026.2 Help

非同期コードをデバッグする

非同期コードのデバッグは、タスクが 1 つのスレッドでスケジュールされ、別のスレッドで実行されることが多いため、困難です。 各スレッドには独自のスタックトレースが存在するため、スレッドの開始前に何が起こったかを把握することが困難です。

IntelliJ IDEA は、異なるスレッドのフレーム間の接続を確立することにより、それを容易にします。 これにより、ワーカースレッドからタスクがスケジュールされた場所までさかのぼって、実行がすべて同じスレッド内にあるかのようにプログラムをデバッグできます。

非同期スタックトレースを試すには、次の例をデバッグします。

import java.util.*; import java.util.concurrent.*; public class AsyncExample { static List<Task> tasks = new ArrayList<>(); static ExecutorService executor = Executors.newScheduledThreadPool(4); public static void main(String[] args) { createTasks(); executeTasks(); } private static void createTasks() { for (int i = 0; i < 20; i++) { tasks.add(new Task(i)); } } private static void executeTasks() { for (Task task : tasks) { executor.submit(task); } } static class Task extends Thread { int num; public void run() { try { Thread.sleep(new Random().nextInt(2000)); } catch (InterruptedException e) { e.printStackTrace(); } printNum(); } private void printNum() { // Set a breakpoint at the following line System.out.print(num + " "); } public Task(int num) { this.num = num; } } }

printNum() メソッドのブレークポイントで停止すると、2 つのスタックトレースが利用できます。

  • 現在のスレッド (ワーカー)

  • メインスレッド (タスクがスケジュールされた場所)

Threads タブでは、スタックトレースの 2 つの部分が表示されます。1 つはワーカースレッド用、もう 1 つはスケジューリングスレッド用です。

コンソールの非同期スタックトレース

デフォルトでは、コードをデバッグしたり、 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); }

アノテーションがどのように機能するかをテストするには、次の例を使用できます。

import org.jetbrains.annotations.Async; import java.util.concurrent.*; public class AsyncSchedulerExample { private static final BlockingQueue<Integer> queue = new LinkedBlockingQueue<>(); public static void main(String[] args) throws InterruptedException { new Thread(() -> { try { while (true) { process(queue.take()); } } catch (InterruptedException e) { e.printStackTrace(); } }).start(); schedule(1); schedule(2); schedule(3); } private static void schedule(@Async.Schedule Integer i) throws InterruptedException { System.out.println("Scheduling " + i); queue.put(i); } private static void process(@Async.Execute Integer i) { // Set a breakpoint at the following line System.out.println("Processing " + i); } }

カスタムアノテーションを定義する

プロジェクトに JetBrains アノテーションの依存関係を追加したくない場合は、独自のアノテーションを定義して、デフォルトのアノテーションの代わりに使用することができます。

  1. キャプチャーポイントと挿入ポイントに独自のアノテーションを作成します。 参考として、 Async.java(英語) を参照してください。

  2. Ctrl+Alt+S を押して設定を開き、 ビルド | 実行 | デプロイ | デバッガー | 非同期スタックトレース を選択します。

  3. アノテーションの構成 をクリックします。

  4. 非同期アノテーションの構成 ダイアログで、 追加 をクリックして、カスタムアノテーションを 非同期スケジュールアノテーション および 非同期アノテーションを実行する に追加します。

リモート 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 スタックトレースは、 フレーム タブの 取得できませんでした でマークされます。 この動作は 設定 | ビルド、実行、デプロイ | デバッガー | Async スタックトレース で制御できます。

デバッガーのオーバーヘッドの測定および管理については、 デバッガーのオーバーヘッドを監視する を参照してください。

2026 年 7 月 14 日