Overview

Debugging a remote Java Application can be handy in more than one case.

The Application

Let’s start with writing an application.

The Application

What’s do it to find that using JDK’s tooling.このチュートリアルで、JDK のツールを使用してそれを行う方法を発見します。 6756>

public class OurApplication { private static String staticString = "Static String"; private String instanceString; public static void main(String args) { for (int i = 0; i < 1_000_000_000; i++) { OurApplication app = new OurApplication(i); System.out.println(app.instanceString); } } public OurApplication(int index) { this.instanceString = buildInstanceString(index); } public String buildInstanceString(int number) { return number + ". Instance String !"; }}

JDWP: The Java Debug Wire Protocol

Java Debug Wire Protocol は、デバッグ担当者とデバッガー間の通信に Java で使用されるプロトコルです。 デバッガーはデバッグされるアプリケーションであり、デバッガーはデバッグされるアプリケーションに接続するアプリケーションまたはプロセスです。

両方のアプリケーションは同じマシンまたは異なるマシンで実行されます。 ここでは、後者に焦点を当てます。

3.1. JDWP のオプション

デバッグ用アプリケーションを起動するとき、JVM コマンドライン引数で JDWP を使用します。

その呼び出しには、オプションのリストが必要です。 dt_shmem は Windows 上で、両方のプロセスが同じマシンで実行されている場合のみ動作するが、 dt_socket はすべてのプラットフォームで互換性があり、プロセスが異なるマシンで実行できる

  • server は必須のオプションではない。 このフラグがオンの場合、デバッガにアタッチする方法を定義する。 addressオプションで定義されたアドレスを通してプロセスを公開するかどうかである。 そうでなければ、JDWPはデフォルトのものを公開します
  • suspendは、JVMがサスペンドしてデバッガがアタッチするのを待つかどうかを定義します
  • addressは、アドレス、一般的にはポート、デバッガによって公開されたものを含むオプションです。 また、文字列として変換されたアドレスを表すこともできます (Windows でアドレスを指定せずに server=y を使用する場合は、javadebug のようになります)
  • 3.2. Launch Command

    リモートアプリケーションを起動することから始めましょう。 Java 5 までは、JVM 引数 runjdwp は他のオプション debug:

    java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000

    JDWP を使用するこの方法はまだサポートされていますが、将来のリリースでは削除される予定です。 可能な限り、より新しい表記法を使用することを推奨します。

    3.3. Java 9 以降

    最後に、JDWP のオプションの 1 つが、Java のバージョン 9 のリリースに伴って変更されました。 これは、1 つのオプションにしか関係しないので、非常に小さな変更ですが、リモート アプリケーションをデバッグしようとしている場合は、違いが出てきます。 古い表記である address=8000 は localhost にのみ適用されます。 古い動作を実現するために、アスタリスクとコロンをアドレスのプレフィックスとして使用します (例: address=*:8000)。

    ドキュメントによると、これは安全ではないため、可能な限りデバッガーの IP アドレスを指定することが推奨されています。

    java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=127.0.0.1:8000

    JDB: The Java Debugger

    JDB (Java Debugger) は JDK に含まれているツールで、コマンドラインからデバッガーのクライアントを便利に提供するために考えられました。 このモードは、JDB を実行中の JVM にアタッチします。 他の実行モードとして listen や run がありますが、ローカルに実行されているアプリケーションをデバッグするときにほとんど便利です:

    jdb -attach 127.0.0.1:8000> Initializing jdb ...

    4.1. ブレークポイント

    1 節で紹介したアプリケーションにいくつかのブレークポイントを設定して、作業を続けましょう。

    コンストラクタにブレークポイントを設定します:

    > stop in OurApplication.<init>

    String クラスの完全修飾名を使用した静的メソッド main に別のブレークポイントを設定します:

    > stop in OurApplication.main(java.lang.String)

    最後に、インスタンスメソッド buildInstanceString に最後のブレークポイントを設定します。

    > stop in OurApplication.buildInstanceString(int)

    これでサーバー アプリケーションが停止し、デバッガー コンソールに次のように表示されるはずです。instanceString が出力されている行です。

    > stop at OurApplication:7

    ブレークポイントが特定の行で定義された場合、in の代わりに stop の後に at が使用されることに注意してください。 ナビゲートと評価

    ブレークポイントを設定したので、cont を使用して、7 行目のブレークポイントに到達するまでスレッドの実行を継続しましょう。

    コンソールに次のように表示されます。

    > Breakpoint hit: "thread=main", OurApplication.main(), line=7 bci=17

    注意として、次のコード部分を含む行で停止しました。

    停止したので、デバッガーは staticString、アプリの instanceString、ローカル変数 i を評価し、最後に他の式を評価する方法を見ています。

    Let’s print staticField to the console:

    > eval OurApplication.staticStringOurApplication.staticString = "Static String"

    私たちは static フィールドの前にクラスの名前を明示的に置いています。

    次に、appのインスタンスフィールドを表示してみましょう:

    > eval app.instanceStringapp.instanceString = "68741. Instance String !"

    次に、変数iを見てみましょう:

    > print ii = 68741

    他の変数とは異なり、ローカル変数はクラスやインスタンスを指定する必要がありません。 print は eval とまったく同じ動作であることもわかります。どちらも式または変数を評価します。

    コンストラクターのパラメーターとして整数を渡した OurApplication の新しいインスタンスを評価します。

    この識別子は、以前に stop コマンドで使用したものとまったく同じです。

    > clear OurApplication:7Removed: breakpoint OurApplication:7

    ブレークポイントが正しく削除されたかどうかを確認するには、引数なしで clear を使用します。 これにより、削除したブレークポイントを除いた既存のブレークポイントのリストが表示されます:

    > clearBreakpoints set: breakpoint OurApplication.<init> breakpoint OurApplication.buildInstanceString(int) breakpoint OurApplication.main(java.lang.String)

    Conclusion

    I:in this quick article, we’ve discovered how to use JDWP together with JDB, both JDK tools.

    .JDWP と JDB を使用する方法を説明しました。