goでJavaのクラスファイルのパーサを書いた

そういえば、書いたことがないなぁと思って、Javaのクラスファイルのパーサを書きました。 Java SE 15のJVM Specification だけを見ながら フルスペックのクラスファイルのパーサを書きました。

書いたけど、パース出来るだけで pretty printが出来たり、なんかいい感じのAPIが生えてたりするわけではないです。

元々、emc(enhanced memory calculator) のために tinycedar/classp の フォークである wreulicke/go-java-class-parser を弄っていましたが メモリ計算のためのツールのために実装したので、フルスペックのパーサではなく、必要な部分しか実装していません。

実装の流れとしては、class File Format の項を上から読みながら実装していきました。 ハマったところは何個かあって、以下のようなところでハマりました。

  • Long/DoubleのConstantはなぜかConstantPoolのindexを1つ先にずらすこと
  • LineNumberTable attributeの場合になぜか、attributeLengthとlineNumberTableLengthから計算できる消費するバイト数が一致しないこと
  • uint8のところをuint16で読み取りしていて、位置がズレてデバッグが大変
  • パースする処理を単純に飛ばしてしまっていて、これまた位置がずれて大変

実装に掛かった時間としては、色々やりながら、大体2日で終わりました。 まだちょっと直せる部分とかはあるのと、APIとしては弱いので もう少し弄ろうと思います。

たぶん、これから互換性が失われるところがいくつか出ると思います。 終わり。

コードはここに置いてあります。