いけむランド

はてダからやってきました

勉強中 (1)

とりあえず試しに 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 のフォーマットと配列と文字列の関係がよくわからない。
少なくとも上の方法はスマートじゃないというのはわかる。
ここらへんはもっと調べる必要がありそう。