とりあえず試しに Java クラスファイルの中身を表示する javap みたいなディスアセもどきを BCEL を写経する感じで書いているのだが、途中でわからずに調べたことをまとめておく。
文字列からクラス
Atrribute のタグがコンスタントプールに文字列で格納されているため、それを直接クラス名と解釈させて、メソッドを呼び出せるようにしようと考えた。つまり
object = Class.forName().newInstance();
みたいなことをしたかった。これを Ruby でやろうとすると
@object = Module.const_get(name).new()
となる。Java だと引数なしコンストラクタ以外のメソッド呼び出しは若干面倒になるが、Ruby だと new() 以外も同じルールで呼べるみたい。
エンディアンとかビット操作
Java みたいに readInt() とか readUTF() みたいな読み出しと型設定を一度にやってくれる手段を探したが、よくわからなかった。
ぐーぐる先生に尋ねると、どうも pack/unpack を使う例が多々見られたので、試行錯誤で試してみた。
class File def readU8() readU4() << 32 | readU4() end def readU4() readU2() << 16 | readU2() end def readU2() readU1() << 8 | readU1() end def readU1() getc() end end class ConstantInteger def parse(file) @value = [file.readU4()].pack("V").unpack("i")[0] end end class ConstantFloat def parse(file) @value = [file.readU4()].pack("V").unpack("f")[0] end end class ConstantLong def parse(file) @value = [file.readU4(), file.readU4()].reverse!().pack("VV").unpack("q")[0] end end class ConstantDouble def parse(file) @value = [file.readU4(), file.readU4()].reverse!().pack("VV").unpack("d")[0] end end
とりあえずは動くけど、pack/unpack のフォーマットと配列と文字列の関係がよくわからない。
少なくとも上の方法はスマートじゃないというのはわかる。
ここらへんはもっと調べる必要がありそう。