2019年3月31日日曜日

jdb でリモートデバッグを行う

貰った Java プログラムが不可解な動きをするので、それを追うために jdb を使うことにした。

幸いにも今までそのレベルの問題に遭遇したことが無かったため、 jdb の使い方自体知らない。

勉強したのでその内容を記す。

環境

  • OS: Windows 10 Pro
  • Java: java version "1.8.0_201"

Java プログラム

テスト用にこんなプログラムを用意。

/**
 * Main
 */
public class Main {
    public static void main(String[] args) {
        String message = getMessage();
        System.out.printf("Hello, %s!\n", message);
    }

    private static String getMessage() {
        return "mikoto2000";
    }
}

コンパイル

-g オプションを付けてコンパイル。

javac -g .\Main.java

Main.class が生成される。

デバッグ

jdb から対象プログラムを直接実行する方法と、 jdb 接続まちしているプログラムに jdb で接続する方法(リモートデバッグ)がある。

jdb から直接実行

jdb の引数にクラスパスとクラス名を渡して実行。

> jdb -classpath . Main
jdbの初期化中...
> stop in Main.main
遅延したブレークポイントMain.main。
クラスがロードされた後に設定されます。
> run
Mainの実行
捕捉されないjava.lang.Throwableの設定
遅延した捕捉されないjava.lang.Throwableの設定
>
VMが開始されました: 遅延したブレークポイントMain.mainの設定

ヒットしたブレークポイント: "スレッド=main", Main.main()、行=6 bci=0
6            String message = getMessage();

main[1] next
>
ステップが完了しました: "スレッド=main", Main.main()、行=7 bci=4
7            System.out.printf("Hello, %s!\n", message);

main[1] cont
> Hello, mikoto2000!

アプリケーションが終了しました

リモートデバッグ

「TCP ポート 1234 で jdb を待ち受けて、 jdb が接続されるまでプログラムをスタートしない」 としようとする場合、次のような手順を実施。

デバッグ対象プログラム実行

以下コマンドでデバッグ対象プログラムを実行する。

java -cp . -agentlib:jdwp=transport=dt_socket,server=y,address=1234 Main
  • agentlib:jdwp: Java Debug Wire Protocol を使用してデバッグしますよと宣言
  • transport=dt_socket: トランスポートに使うライブラリの指定
  • server=y: サーバーを起動して待ち受けますよという宣言
  • address=1234: 1234 番ポートで待ち受けますよと宣言

デバッガ実行

以下コマンドでデバッガを実行する。

jdb -attach 1234

Windows の場合は、 SocketAttach コネクタで接続する必要がある。

jdb -connect com.sun.jdi.SocketAttach:hostname=localhost,port=1234

あとは、直接プログラムを起動するのと同じですね。

以上。

細かい使い方は参考資料を参照のこと。

参考資料

0 件のコメント:

コメントを投稿