疑問
eclipseでJavaを書いてデバッグをしているとき、自前で書いたメソッドだけではなく、標準APIのメソッドにもステップインしてソースコードを表示させることができます。
たとえば、println()にステップインすると、PrintStream.classというクラスファイルが開かれて、println()の実装が確認できます。
いやしかし、クラスファイルって.javaファイルをコンパイルしたものだから人が読める形式ではないんじゃないの? なんでソースコードが見れるの? もしかしてクラスファイルってテキストエディタとかでも開いて読める?
この時点で知っていたこと:
- .javaファイルをコンパイルすると.classファイルができる。JVMはクラスファイルを実行している。
- Javaではクラスはパッケージで管理され、パッケージはモジュールで束ねられる。
- 標準APIに対応するモジュールはjava.baseでこいつはJDKに付いてくる(また勝手にrequires指定されるからコード書くときに標準APIを使える)
- なのでPrintStream.classはjava.baseモジュールのどこかに居る。
というわけで、エクスプローラからJDKのフォルダ配下にあるjmodsフォルダの中のjava.base.jmodを引っ張ってきて展開してみました。classes > java > ioとたどるとPrintStream.classが見つかりました。
試しにテキストエディタで開いてみると、なんか読める箇所もあるし読めない箇所もある感じでした。
はて、ではなんでeclipse上だと読める形で表示されるのか。
eclipseが気を利かせてJavaの逆コンパイラを実行してくれていたから
いろいろググった結果、
- クラスファイルはJavaバイトコードと呼ばれる形式である。
- これは逆コンパイラを通すと(ある程度まで)ソースコードに復元することができる。
- eclipseにはプラグインとして逆コンパイラが搭載されている。
ということがわかりました。なるほど。
実際、eclipseのパッケージエクスプローラからJREシステムライブラリー > java.base > java > io > PrintStream.class とたどり、右クリック > 次でクラスを開く を選択すると逆コンパイラと思われる一覧が現れました。
その中の1つであるCFRを選んで開くと、冒頭でステップインしたときと同様にPrintStream.classを読める形で表示させることができました。ステップインしたときに裏で逆コンパイラをかませてくれていたのね。
おまけ
逆コンパイラ云々とは別の話として、標準APIについてはソースコード(.javaファイル)もJDKに同梱されているようです。
JDKのフォルダ配下のlib > src.zip を展開したものがそれのようで、PrintStream.classに対応する.javaファイルは、この中の java.base > java > io > PrintStream.java に見つけました。
chatGPTに聞いたところ、
標準APIのソースコードが配布されているのは、開発者がデバッグやソースコードの参照を容易にするための便利さを提供するためです。
ということでした。1次ソースは見つけられなかったけど、さもありなんという理由なので納得することにしました。
参考