#chiroito ’s blog

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

JShell 自体をデバッグしてみた

Java Bug System を見ていたら JShell 自体のデバッグを見つけたので、パッチを書こうと思いJShellについて調べてみた。

使い方や 2 つの JVM が動くぐらいは知っていたけど、具体的には知らないので調べてみました。

試しにjshellコマンドを実行してからjmcjcmdを確認するとjdk.internal.jshell.tool.JShellToolProviderjdk.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) {
(略)
}