あやみつさんの覚書き

メモや覚書きなど

asm

MOD作成の際にasmに触れる機会に遭遇したので少し覚書きを。
あ、Javaです。


asmの公式ページはこちら→http://asm.ow2.org/
javadocはこちら→http://asm.ow2.org/asm33/javadoc/user/index.html

私が今この記事を書いているときはasmのjavadocは3.3ですが、実際に使用しているバージョンは4.0です。なんででしょ。
今のasmに対する私の印象は「実行時にクラスが読み込まれた時点にそのクラスに改変を施すためのライブラリ」です。長いと印象つきにくいですね。
私自身まだ全然わかっていないのでご了承ください。

今回は簡単な構造についてだけ書きます。

私がやっていた環境ではbyte配列が与えられていました。
そのbyte配列に改変を施すことで実行時のクラスに改変を加え、実際に実行している模様。

まず必要(なのかな?)なの

  • ClassNode
  • ClassReader
  • ClassWriter

流れとしては
ClassReaderにbyte配列いれる

ClassNodeにClassReaderで解析したのをいれてもらう(?)

ClassNodeをいじって改変を加える

ClassWriterにClassNodeいれてbyte配列にもどしてそれをかえす

あってるかわからないですが、現状の私の捉え方はこんな感じです。

それをソースであらわすと

public byte[] transform(byte[] arrayOfByte) {
        ClassNode classNode = new ClassNode();

        // byte配列いれる
        ClassReader classReader = new ClassReader(arrayOfByte);

        // ClassReaderからClassNodeにいれてもらう、0は何かはおいといて
        classReader.accept(classNode, 0);

        //
        // ClassNodeにいろいろして改変を加える
        //

        // COMPUTE_FRAMESとCOMPUTE_MAXSはClassWriterのstatisなフィールド
        // 適宜、参照やstatic importを
        ClassWriter classWriter = new ClassWriter(COMPUTE_FRAMES | COMPUTE_MAXS);

        // ClassNodeからClassWriterにいれてもらう
        classNode.accept(classWriter);

        return classWriter.toByteArray();
}

こんな感じになります。

ClassReader(攻め)×ClassNode(受け)と、
ClassNode(攻め)×ClassWriter(受け)ですね。
わかりやすいですね!ね!

このとき、改変に失敗したりするとjava.lang.VerifyErrorでたりします。
今ちょうどそれに苦しめられてます。しにそうです。

今回はこんな感じで。

[覚えておくこと]

  • ClassReaderは攻め
  • ClassNodeは受けと攻めの両方
  • ClassWriterは受け

・・・さて、英文のソースやjavadoc読んで理解深めましょうねー・・・