Java Bug System を見ていたら JShell 自体のデバッグを見つけたので、パッチを書こうと思いJShellについて調べてみた。
使い方や 2 つの JVM が動くぐらいは知っていたけど、具体的には知らないので調べてみました。
試しにjshell
コマンドを実行してからjmc
やjcmd
を確認するとjdk.internal.jshell.tool.JShellToolProvider
とjdk.jshell.execution.RemoteExecutionControl
が起動するのが確認できます。
人間がふれ合うクラスはjdk.internal.jshell.tool.JShellToolProvider
です。
jdk.internal.jshell.tool.JShellToolProvider
の実行時引数を確認したところ以下のような感じでした。
java -Dapplication.home=C:\Oracle\Java\jdk-11 -Xms8m -Djdk.module.main=jdk.jshell jdk.internal.jshell.tool.JShellToolProvider
これに-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:12345
を付けてデバッグできるようにします。
全部付けるとこんな感じ。
java -Dapplication.home=C:\Oracle\Java\jdk-11 -Xms8m -Djdk.module.main=jdk.jshell -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:12345jdk.internal.jshell.tool.JShellToolProvider
デバッグが出来るようになりましたが、気になるのはユーザからの入力を待つ場所あたりかと。
これは、jdk.jshell
モジュールの中ではjdk.internal.jshell.tool.ConsoleIOContext
クラスのpublic String readLine(String prompt, String prefix) throws IOException, InputInterruptedException
メソッドでユーザの入力を待ちます。
@Override public String readLine(String prompt, String prefix) throws IOException, InputInterruptedException { (略) try { return in.readLine(prompt); } catch (UserInterruptException ex) { (略) }
in
のオブジェクトはjdk.internal.le
モジュールのjdk.internal.jline.console.ConsoleReader
です。
jdk.internal.le
モジュールでは、jdk.internal.jline.internal.InputStreamReader
クラスのpublic int read(char[] buf, int offset, int length) throws IOException
メソッドでユーザの入力を待ちます。
@Override public int read(char[] buf, int offset, int length) throws IOException { (略) int off = bytes.arrayOffset() + bytes.limit(); int was_red = in.read(bytes.array(), off, to_read); if (was_red == -1) { (略) }