1. 概要

このチュートリアルでは、いくつかの高度なIntelliJデバッグ機能について説明します。

デバッグの基本はすでにわかっていることを前提としています(デバッグの開始方法、ステップインステップオーバーアクションなど)。 そうでない場合は、この記事で詳細を参照してください。

2. スマートステップイントゥ

doJob(getArg1()、getArg2())のように、1行のソースコードで複数のメソッドが呼び出される場合があります。 Step Into アクション(F7)を呼び出すと、デバッガーは、評価のためにJVMで使用される順序でメソッドに入ります: getArg1 getArg2 – [X161X ]doJob。

ただし、すべての中間呼び出しをスキップして、ターゲットメソッドに直接進むことができます Smart StepIntoアクションでそれが可能になります。

デフォルトではShift+ F7にバインドされ、呼び出されると次のようになります。

これで、続行するターゲットメソッドを選択できます。 また、IntelliJは常に最も外側のメソッドをリストの一番上に置くことに注意してください。 つまり、 Shift + F7 |を押すと、すぐに移動できます。 Enter

3. ドロップフレーム

関心のある処理がすでに行われていることに気付く場合があります(例: 現在のメソッド引数の計算)。 この場合、現在のJVMスタックフレームをドロップして再処理することができます。

次の状況を考慮してください。

getArg1 処理のデバッグに関心があるとすると、現在のフレームを削除します( doJob メソッド)。

これで以前の方法になりました:

ただし、呼び出し引数はこの時点ですでに計算されているため、現在のフレームも削除する必要があります

これで、 StepIntoを呼び出して処理を再実行できます。

4. フィールドブレークポイント

非プライベートフィールドは、セッターではなく直接、他のクラスによって変更される場合があります(これは、ソースコードを制御しないサードパーティのライブラリの場合です)。

このような状況では、変更がいつ行われるかを理解するのが難しい場合があります。 IntelliJでは、フィールドレベルのブレークポイントを作成してそれを追跡できます。

これらは通常どおりに設定されます。フィールド行の左側のエディターガターを左クリックします。 その後、ブレークポイントプロパティを開いて(ブレークポイントマークを右クリック)、フィールドの読み取り、書き込み、またはその両方に関心があるかどうかを構成することができます

5. ブレークポイントのロギング

アプリケーションに競合状態があることはわかっていても、正確にどこにあるのかわからない場合があります。 特に新しいコードで作業しているときは、それを突き止めるのは難しいかもしれません。

プログラムのソースにデバッグステートメントを追加できます。 ただし、サードパーティのライブラリにはそのような機能はありません。

IDEはここで役立ちます– 一度ヒットすると実行をブロックしないブレークポイントを設定できますが、代わりにログステートメントを生成します

次の例を考えてみましょう。

public static void main(String[] args) {
    ThreadLocalRandom random = ThreadLocalRandom.current();
    int count = 0;
    for (int i = 0; i < 5; i++) {
        if (isInterested(random.nextInt(10))) {
            count++;
        }
    }
    System.out.printf("Found %d interested values%n", count);
}

private static boolean isInterested(int i) {
    return i % 2 == 0;
}

実際のisInterested呼び出しのパラメーターをログに記録することに関心があるとします。

ターゲットメソッドに非ブロッキングブレークポイントを作成しましょう( Shift +左側のエディターガターを左クリックします)。 その後、そのプロパティを開き(ブレークポイントを右クリック)、ターゲット式をlogに定義します。

アプリケーションを実行すると(デバッグモードを使用する必要があることに注意してください)、次の出力が表示されます。

isInterested(1)
isInterested(4)
isInterested(3)
isInterested(1)
isInterested(6)
Found 2 interested values

6. 条件付きブレークポイント

特定のメソッドが複数のスレッドから同時に呼び出され、特定の引数に対してのみ処理をデバッグする必要がある場合があります。

IntelliJは、ユーザー定義の条件が満たされた場合にのみ実行を一時停止するブレークポイントの作成を許可します

上記のソースコードを使用した例を次に示します。

これで、指定された引数が3より大きい場合にのみ、デバッガーはブレークポイントで停止します。

7. オブジェクトマーク

これは最も強力で、最も知られていないIntelliJ機能です。 本質的には非常に単純です–カスタムラベルをJVMオブジェクトに添付できます

それらをデモンストレーションするために使用するアプリケーションを見てみましょう。

public class Test {

    public static void main(String[] args) {
        Collection<Task> tasks = Arrays.asList(new Task(), new Task());
        tasks.forEach(task -> new Thread(task).start());
    }

    private static void mayBeAdd(Collection<Integer> holder) {
        int i = ThreadLocalRandom.current().nextInt(10);
        if (i % 3 == 0) {
            holder.add(i);
        }
    }

    private static class Task implements Runnable {

        private final Collection<Integer> holder = new ArrayList<>();

        @Override
        public void run() {
            for (int i = 0; i < 20; i++) {
                mayBeAdd(holder);
            }
        }
    }
}

7.1. マークの作成

アプリケーションがブレークポイントで停止し、スタックフレームからターゲットに到達できる場合、オブジェクトにマークを付けることができます。

それを選択し、 F11 Mark Object アクション)を押して、ターゲット名を定義します。

7.2. マークを表示

これで、アプリケーションの他の部分でもカスタムオブジェクトラベルを確認できます。

すばらしいのは、マークされたオブジェクトが現時点でスタックフレームから到達できない場合でも、その状態を確認できることです式の評価ダイアログを開くか、新しい時計を追加してマークの名前の入力を開始します。

IntelliJは、_DebugLabelサフィックスを付けて完成させることを提案しています。

評価すると、ターゲットオブジェクトの状態が表示されます。

7.3. 条件としてマーク

ブレークポイント条件でマークを使用することもできます。

8. 結論

マルチスレッドアプリケーションのデバッグ中に生産性を大幅に向上させるいくつかの手法を確認しました。

これは通常、やりがいのある作業であり、ここではツールの助けの重要性を過小評価することはできません。