大きな一週間でした。私は現在、近刊予定のデバッグ本の最終ドラフトを見直しています。これは常に冷静でエキサイティングな瞬間です。突然、すべての月の仕事が「現実」になる瞬間。
また、YouTube 用に 9 本のビデオを録画したので、コースの合計ビデオ数は 29 本になりました (さらに多くのビデオを作成する予定です)。 2 つの追加の無料コースを開始します。1つは完全な初心者を対象としています。
もう 1 つは、近日中に開始する最新の Java プログラミングに関するものです。両方ともで無料で利用できます (必須の「いいね、チャンネル登録、共有」)。
今週の投稿では、ブレークポイントについて説明します。ブレークポイントと言うときの意味は、実際には単なる「ライン ブレークポイント」であるため、長くなります。以下に示すように、他にもたくさんあります。
Scale でのデバッグの第 4 部へようこそ。変数名!
このセクションでは、デバッグ時の最も基本的な作業単位であるブレークポイントについて説明します。しかし、ただ壊れるだけではありません。
最初の記事で、最も基本的なブレークポイントについて説明しました。今回は、あまり知られていないいくつかのニュアンスについて、もう少し深く掘り下げます。
条件付きブレークポイントから始めます。条件付きブレークポイントを使用すると、ブレークポイント ヒットの条件を定義できます。これにより、スレッドがブレークポイントで常に停止するのを防ぎます。これについては、前のビデオで作成した myThread マーカー オブジェクトで説明しました。
この場合、現在のスレッドと異なる場合にのみ停止します。つまり、このブレークポイントは、別のスレッドが呼び出した場合にのみヒットします。これは、デッドロックや競合などのスレッド関連の問題を検出する優れた方法です。この機能は非常に重要な機能であるため、繰り返し説明する価値があります。
メソッドのブレークポイントはかなり問題があります。
復習として、メソッド内の任意の行に行ブレークポイントを配置すると、ブレークポイントはそこで停止します。これはいたるところにあるため、単に「ブレークポイント」と呼んでいます。
control-F8 または Mac ではCommand-F8
で標準の行ブレークポイントを切り替えることができます。
メソッドのブレークポイントは、メソッドに入ると停止します。これは無駄だと思うかもしれません。行ブレークポイントを使用しないのはなぜですか?
あなたは正しいでしょう。メソッド ブレークポイントは非常に遅いので、使用しないでください。
メソッドのブレークポイントは非常に遅いため、通常は IDE によってエミュレートされることに注意してください。行ブレークポイントを使用してメソッドブレークポイントをシミュレートするだけです。これは、IDE のユーザーである私たちにとってほとんどシームレスですが、これについて知る必要があります。これは、以前はそうではなかったためです。
メソッドのブレークポイントの遅さについて文句を言う StackOverflow のユーザーからのメッセージを今でも見つけることができます。
メソッド ブレークポイントの使用例を確認するために、[ブレークポイントの管理] ウィンドウに移動します。名前が Prime で始まるクラスの文字 I と S で始まるすべてのメソッドを中断したいとします。
このような式を使用して、パターンに基づいてそのようなすべてのメソッドを停止することで、これを行うことができます。これは大げさに思えるかもしれませんが、サブクラスが命名規則に従い、関連するメソッドが多数ある抽象基本クラスがある場合、実際には非常に便利です。
すべてを追跡したい場合、このアプローチを使用してそれを行うことができます。ここでトレースポイントを使用して、非常に詳細なログを取得することもできます。トレースポイントについては、数分で説明します。
フィールド ウォッチポイントは、通常のブレークポイントではありません。ウォッチポイントは、フィールドの値が変更されるたび、または読み取られるたびに停止します。これは、一部のコードが変数を変更したり、フィールド値がコードに伝播する方法を見つけたりするケースをキャッチするための非常に優れた方法です。
このダイアログを使用して、読み取り操作、書き込み操作、またはその両方で停止するかどうかを調整できることに注意してください。他のブレークポイントと同じように、ウォッチポイントを条件付きにすることもできます。
コードが停止するポイントではないため、ブレークポイントではなくウォッチポイントと呼ばれます。フィールド自体ではなく、アクセスポイントで停止します。
IDE は、すべてのブレークポイントに管理 UI を提供します。既にあるブレークポイントを管理し、ビュー ブレークポイント メニューで新しいブレークポイントを作成できます。ビュー ブレークポイント メニュー オプションから開くか、 Shift-Control-F8
キーの組み合わせを使用できます。
Mac では、コントロール キーの代わりにコマンドを使用する必要があることに注意してください。
このダイアログでは、ブレークポイントを無効化、削除、および編集できます。ここには、すぐに説明する多くのオプションがあることに気付くでしょう。ここからブレークポイントを追加できます。興味深いオプションがいくつかありますが、ここでは単純なフィールド ブレークポイントを追加します。
例外がスローされたときに停止するブレークポイントを設定できます。しかし、それは少し問題です。選択肢は 2 つあります。まず、特定の例外を名前でキャッチできます。これは、スローされる例外が事前にわかっている場合に便利です。
しかし、これが発生したケースはあまり思いつきません。また、例外がスローされた行も知りませんでした。
より価値のあるユースケースは、すべての例外をキャッチすることです。これが便利な理由は、デバッグ中にコンソールを見ないことがあるためです。そこに例外が記録される可能性があり、それらを完全に見逃す可能性があります。
デバッグ セッションを再開すると、これらの例外を見逃す可能性があります。しかし、ブレークポイントが例外で突然停止した場合、それを見逃すことはほとんどありません。問題は、すべての例外をキャッチすることがデフォルトで壊れていることです!
残念ながら、これは単純な主要なメイン アプリケーションで表示するのが難しいため、デモを単純なスプリング ブート アプリケーションに切り替えました。この場合、アプリケーションの内容は重要ではありません。例外のキャッチを有効にして、何が起こるか見てみましょう…
キャッチを有効にした後、続行しようとしましたが、すぐにブレークポイントに何度も何度もヒットします。このコードは、バックグラウンドで WebService をポーリングします。その WebService には HTTP ヘッダーがないため、そのヘッダーを解析するコードは NumberFormatException で失敗します。
Java は、そのコードが書かれたときに数値ヘッダーを解析する別の方法を提供しなかったため、有効な例外をスローするコードにこだわっています。
では、何ができるでしょうか?これにより、事実上、ほとんどすべての実際のアプリケーションで、例外による停止が役に立たなくなります。
ウィンドウを少し動かしてから、ズームインして、ここで何をしているのかを見てみましょう。
これで、クラス フィルターを定義できます。両方のフィルターの前にマイナス文字を付けて、これを除外フィルターに変えていることに注意してください。ここでは、すべての Java パッケージとすべての Sun パッケージのフィルターを定義します。つまり、これらのパッケージ内で処理されるすべての例外は壊れません。
[OK] を押すと、[続行] を押すことができ、アプリケーションは問題のある例外で中断することなく実行されます。他の例外は通常どおり機能し、コードで何かが壊れたときに通知します!
これが IDE のデフォルトではないのは驚くべきことです。それがなければ、機能は実質的に役に立ちません。
トレースポイントまたはログポイントは、私たちが持っている最も重要なタイプのブレークポイントの一部です。ガターを Shift キーを押しながらクリックすると、トレースポイントを追加できます。これにより、おなじみのブレークポイント ダイアログが開きますが、見た目が少し異なります。まず、次のことに注意してください。
一時停止オプションはチェックされていません。中断チェックボックスをオフにすることで、任意のブレークポイントをトレースポイントに変換できることに注意してください。デフォルトでは、ブレークポイントはブレークします。現在のスレッドを停止して一時停止するので、アプリケーション スタックをゆっくりと調べて、何が起こっているかを確認できます。
トレースポイントは現在のスレッドを中断しません。アプリケーションはブレークポイントに到達し、停止することなく実行を続けます。これは非常に画期的なことです。
まあ、あなたはしません。代わりに、他にもいくつかのことができます…
ブレークポイントに到達するたびに「ブレークポイント ヒット」という言葉をログに記録できますが、トレースポイントが 1 つしかなく、そのポイントに到達したかどうかだけを知りたい場合を除き、これはあまり役に立ちません。トレースポイントに到達するたびにスタック トレースを出力できます。これは実際、より便利です。しかし、それほどではありません。
リスト内の多くのトレースを読んで、最後までやり抜くのは困難です。私が注目したいのは別のことです。
ガターで Shift キーを押しながらクリックする前に IDE でcnt
値を選択していたため、evaluate と log には既にcnt
値が含まれていることに注意してください。
ここには、印刷したい任意の式を書くことができます。メソッドを呼び出して、説明的な文字列などを書き込むことができます。これは文字通り、コードに動的に追加できる標準のログ ステートメントです。条件付きブレークポイントと同様に、このトレースポイントを条件付きにすることができることに注意してください。
つまり、この時点で任意の値を出力できます。他のロガーと同じように。これは素晴らしい機能です。これらのトレースポイントで前述したメソッド ブレークポイントを想像してみてください。大規模なログを即座に記録できます。 OKを押しましょう。
そして、このプログラムを実行します。コードに書き込んだかのように、コンソールに出力されたトレースポイントに追加したログを確認できます。
デバッグをスケールアップしたら、グループ化と名前付けは非常に重要です。
説明を使用してブレークポイントに名前を付け、そのセマンティックな意味を示すことができます。これは、多くのブレークポイントを扱う場合に非常に役立ちます。ファイル、パッケージなどに基づいてグループ化することもできます。
しかし、優れた点は、ブレークポイントのカスタム グループを作成し、1 つのトグルでグループ内のブレークポイントを無効にできることです。とても便利です!
これにより、ある状態に到達しようとするときに面倒な [続行] を押す必要がなくなり、多くのブレークポイントを管理できます。
しかし、ここでの真の価値は規模にあります。複数のトレースポイントが同時に実行される複雑なデバッグ セッションがあるとします。
セッションをグループ化してブレークポイントを無効にし、別のブランチに切り替えて別のものをデバッグできます。終わったら元の場所に戻ってください。
ブレークポイントが常にヒットし、特定のスタックのみが必要な場合があります。
別のブレークポイントまたは例外に到達するまで、ブレークポイントを無効にすることができます。その時点で、ブレークポイントは自動的に有効になります。これにより、特定のパスウェイのみをテストしたい場合に、常に続行を押す必要がなくなります。
これは例外と例外ブレークポイントでも機能し、後で動作を決定できます。もう一度無効にしますか、それとも通常どおり続行しますか?
これは、特定の経路のみを通過する障害の場合に非常に役立ちます。最初のメソッドにトレースポイントを追加できます。次に、そのトレースポイントで必要な実際のブレークポイントを無効にします。
インスタンス フィルターを使用すると、特定のオブジェクト インスタンスからのブレークポイントのみを受け入れることができます。
ウォッチで「this」とマークされた現在のオブジェクトのインスタンスに注目してください。アットマークの後に数字の 656 が続くことに注意してください。
これは、他のプログラミング言語のポインターに相当する Java オブジェクト ID です。インスタンス フィルターでは、ブレークポイントを制限して、特定のオブジェクトに対してのみヒットするようにすることができます。
この行のブレークポイントが複数のインスタンスによって頻繁にヒットされるとしますが、特定のオブジェクト インスタンスからの結果のみを気にし、すべてのノイズを除外したいとします。ここをクリックすると、高度な詳細ダイアログを開くことができます。
インスタンス フィルター オプションを確認してから、フィルター処理するインスタンスのオブジェクト ID を入力する必要があります。これは、ブレークポイントが他のインスタンス タイプで停止しないことを意味します。この変更を適用するには、完了を押します。
この時点で、インスタンス フィルターが予期されるブレークポイントでまだ停止していることがわかります…
次のステップは、インスタンス フィルタを別のオブジェクト インスタンスに変更することです。これはテスト用なので、番号を作成しています。
ブレークポイントを右クリックすると、インスタンス フィルターが配置されているため、このダイアログのカスタマイズされたバージョンが表示されることに注意してください。これは非常に優れた機能で、UI の操作が非常に簡単になります。
変更を行ったので、ブレークポイントは壊れなくなりました。
クラス フィルターは、一般的な行ブレークポイントでは意味がありません。クラス フィルターは、フィールド ウォッチポイントまたは例外ブレークポイントを使用する場合に意味があります。
この場合、パブリック フィールドがあります。フィールドへのアクセスをフィルタリングして、主要なメイン クラスからのすべてのアクセスを無視します。別のクラスがフィールドにアクセスすると、ブレークポイントがヒットします。
これは非常に便利です。そうしないと、現在のクラスからウォッチポイントに多くのヒットが表示される可能性があります。しかし、私は他のケースを見たいです。
呼び出し元フィルターは、呼び出し元のメソッドのシグネチャに基づいてフィルターを実装します。それを使用するには、再び詳細メニューに移動する必要があります。ワイルドカードをサポートしているため、呼び出し元を制限して run メソッドのみを許可できます。
メソッド シグネチャに JVM 表記を使用していることに注意してください。これは、後で説明する非常に複雑なテーマです。私のデバッグブックには、それをカバーするセクションがあります。
ここでわかるように、run メソッドは実際にスタック トレースにあるため、メソッドはブレークポイントで停止し続けます。したがって、フィルターが適切に適用され、ブレークポイントにヒットします。
フィルターのクイック編集 UI でブレークポイントを再びカスタマイズできます。この場合、フィルターを変更して、存在しない stop というメソッドを探すようにしました。実際、ブレークポイントは壊れなくなりました。
これは長いビデオでした。このビデオが教育的で包括的であると感じていただければ幸いです。次のビデオでは、ストリームとコレクションのデバッグについて説明します。
ご不明な点がございましたら、コメント欄をご利用ください。ありがとうございました!