#chiroito ’s blog

Java を中心とした趣味の技術について

OpenJDK のテストをデバッグ実行するためいろいろ試みてみた

Java のコードをデバッグ実行するには-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=127.0.0.1:12345みたいな感じのを付けます。これを使って OpenJDK の Java 部分のデバッグができるだろうなと思って試してみました。

jtreg で実行するテストコードにこれを付けたところ、アタッチするまでに気が遠くなるぐらい長い時間がかかり、やっと繋がったと思ったら jtreg のタイムアウトにやられるため実用に耐えられなかったです。

なので、もっと気軽にアタッチできる方法は無いか試してみました。

make で jtreg を使うには configure するときに --with-jtreg=/src/jtreg/build/images/jtreg を付けないといけません。自分がどのオプションで実行したかは build/linux-x86_64-server-fastdebug/configure.log で確認できます。linux-x86_64fastdebug の部分は環境や指定したオプションによって変ります。

jtreg で実行したテストへアタッチ

jtreg でテストを実行する JVM へVM引数を渡すには JTREG="VM_OPTIONS=*****" のような形式でmake の実行時に指定します。***** の部分がVM引数としてテストを実行する JVM へ渡されます。

今回は JTREG="VM_OPTIONS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=127.0.0.1:12345" としています。

> make test TEST="test/jdk/jdk/jfr/startupargs/TestRepositoryPath.java" JTREG="VM_OPTIONS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=127.0.0.1:12345"

Building target 'test' in configuration 'linux-x86_64-server-fastdebug'
Skip building of Graal unit tests because 3rd party libraries directory is not specified
Skip building of Graal unit tests because 3rd party libraries directory is not specified
Running tests using JTREG control variable 'VM_OPTIONS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=127.0.0.1:12345'
Test selection 'test/jdk/jdk/jfr/startupargs/TestRepositoryPath.java', will run:
* jtreg:test/jdk/jdk/jfr/startupargs/TestRepositoryPath.java

Running test 'jtreg:test/jdk/jdk/jfr/startupargs/TestRepositoryPath.java'
[2019-01-02 11:48:15,081] Agent[0]: stdout: Listening for transport dt_socket at address: 12345
[2019-01-02 11:48:32,392] Agent[0]: stderr: openjdk version "13-internal" 2019-09-17
[2019-01-02 11:48:32,397] Agent[0]: stderr: OpenJDK Runtime Environment (fastdebug build 13-internal+0-adhoc.chito.jdk)
[2019-01-02 11:48:32,397] Agent[0]: stderr: OpenJDK 64-Bit Server VM (fastdebug build 13-internal+0-adhoc.chito.jdk, mixed mode)

実行してみると分かりますが、恐ろしく長い時間が掛かりますし、いつになったらアタッチできるのか分かりません。ポートは開くのですがアタッチされる準備は出来ていないようなので、Connection Refused されてしまい「接続できない??」と思うほどです。

jtreg を使わずにテストを実行してみる

これでは OpenJDK を開発する中で軽い気持ちで動作を確認できないので、方法を模索してみました。

各種 IDE 上でテストコードをコンパイルして実行してみようと思ったのですが、IDE ちからがなくて断念。

面倒臭い部分は全て jtreg にやってもらって、実行だけできないかと思い、jtreg が生成するクラスファイルなどを使用することにしました。

make test すると build/linux-x86_64-server-fastdebug/test-support/ ディレクトリ以下にいろいろ作ってくれます。その中にはクラスファイルも含まれるためこちらを使用することとしました。

以下 5 つの変数を使ってテストを実行したいと思います。

  • JAVA_EXE はテストしたい環境の java ファイルを指定します。
  • JAVA_OPTIONS は自分が追加したい VM 引数を指定します。
  • TEST_CLASSPATH はjtregに作成されたクラスファイル群を指定します。
  • TEST_OPTIONS はテストのファイルに記載されているオプションを指定します。
  • TEST_CLASS は実行したいテストクラスを指定します。
> export JAVA_EXE=build/linux-x86_64-server-fastdebug/images/jdk/bin/java
> export JAVA_OPTIONS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=127.0.0.1:12345

> export TEST_CLASSPATH=build/linux-x86_64-server-fastdebug/test-support/jtreg_test_jdk_jdk_jfr_startupargs_TestRepositoryPath_java/classes/jdk/jfr/startupargs/TestRepositoryPath.d
> export TEST_OPTIONS=-XX:StartFlightRecording=name=TestStartRecording,settings=profile -XX:FlightRecorderOptions=repository=./repo
> export TEST_CLASS=jdk.jfr.startupargs.TestRepositoryPath

> ${JAVA_EXE} ${JAVA_OPTIONS} -cp  ${TEST_CLASSPATH} ${TEST_OPTIONS} ${TEST_CLASS}

Listening for transport dt_socket at address: 12345

この方法だと、すぐにアタッチできるようになりタイムアウトもなくなったので、OpenJDK のデバッグライフがより快適になるのではないかと思います。