2014-09-18
【ASM】Javaバイトコードを生成するライブラリ『ASM』が凄い
[ PR ]
ASMというフレームワークをご存知でしょうか。
実は、以下の様な言語・フレームワークに利用され、JRubyやJython、Eclipseなども利用しているのです。
- AspectWerkz
- AspectJ
- BeanShell
- CGLIB
- dynaop
- Clojure
- Groovy
- Jamaica
- JRuby
- Jython
- NetLogo
- Open Quark
- WebSphere sMash
- Coroutines
- fun4j
- EclipseME
- MicroEmulator Sun Java ME emulation for Java SE |
- Fractal
- Dr. Garbage
- Proactive
- Retrotranslator
- RIFE
- R-OSGi
- Terracotta
- Substance L&F
- WindowBuilder
- Javeleon
- EasyBeans
- Ebean
- JDBCPersistence
- JPOX
- OpenEJB
- Oracle BerkleyDB
- Oracle TopLink
- Speedo
- BEA WebLogic
- BTrace
- Byteman
- JiP
- ByCounter
- Limpid Log
- Agitar
- Cobertura
- Eclipse
- JCarder
- SemmleCode
- Structure101
- SonarJ
- Sun Microsystems, Inc.
- TamiFlex
そこで、今回はASMの触りだけを紹介します。
Hello, World
Jarの準備
まず、asm.jarをMavenCentralからダウンロードしてください。(Ivy, Mavenでも可)
Maven Repository: org.ow2.asm » asm
元になるコード
今回は、以下のコードに当たるクラスをASMで生成してみます。
public class HelloFromASM {
public HelloFromASM(){
super();
}
public static void main(String[] args){
System.out.println("Hello, ASM!");
}
}
ソースコード
ASMHelloWorld.java:
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import org.objectweb.asm.*;
public class ASMHelloWorld implements Opcodes {
public static byte[] dump() throws Exception {
ClassWriter cw = new ClassWriter(0);
MethodVisitor mv;
ClassVisitor cv;
cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER, "HelloFromAsm", null, "java/lang/Object", null);
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
mv.visitInsn(RETURN);
mv.visitMaxs(1,1);
mv.visitEnd();
mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
mv.visitCode();
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitLdcInsn("Hello, ASM!");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
mv.visitInsn(RETURN);
mv.visitMaxs(2,1);
mv.visitEnd();
cw.visitEnd();
return cw.toByteArray();
}
public static void main(String[] args) throws Exception {
DataOutputStream out = new DataOutputStream(new FileOutputStream("HelloFromAsm.class"));
out.write(dump());
out.flush();
out.close();
}
}
コンパイル・コード生成
このソースをコンパイルします。
javac -cp asm.jar:. ASMHelloWorld.java
ここからマジックが始まります。
java -cp asm.jar:. ASMHelloWorld
すると、なんと HelloFromASM.class が生成されています!
試しにHelloFromASMを実行してみましょう。
java HelloFromASM
# Hello, ASM!
何が起こったのか
(詳しい解説は、Jasminで同じコードの解説をしているので、そちらを参照してください。)
Javac → Java と実行したのに、classファイルが生成されたのが不思議ですが、実は、ASMが動的にクラスファイルを生成しているのです。
そのため、JavacではなくJavaで実行した際にクラスファイルが出来るのです。
不思議ですね。
>コラム:高次概念「メタ」
人間の頭は、メタな概念に関してはついていけないので、理解出来ないのは当然なのです。
要するに、ASMはメタプログラミングを行っていることが分かります。
ASMのその他の機能
- Javaバイトコードの解析
- 既存Javaバイトコードの変更
- Javaバイトコードの動的生成
- クラスファイルの動的生成
ライセンス
デコンパイリングJava ―逆解析技術とコードの難読化 (Art Of Reversing)
posted with amazlet at 14.09.19
Godfrey Nolan
オライリージャパン
売り上げランキング: 348,592
オライリージャパン
売り上げランキング: 348,592