ASM
ASM 是一個通用的Java字節碼操作和分析框架。
它可以用來修改現有的類或動態地生成類,直接以二進制形式。
ASM提供了一些通用的字節碼轉換和分析算法,可以從這些算法中構建自定義複雜的轉換和代碼分析工具。
ASM提供與其他Java字節碼框架類似的功能,但主要關注性能。
因爲它的設計和實現都儘可能地小和快,所以非常適合在動態系統中使用(當然也可以以靜態的方式使用,例如在編譯器中)。
特性
ASM 並不是生成和轉換已編譯Java類的唯一工具,但它是最近和最有效的工具之一。
可以從 http://asm.objectweb.org 下載。其主要優點有:
-
它有一個簡單、設計良好、模塊化的API,易於使用。
-
爲最新的 Java 版本提供支持。
-
它很小,速度很快,而且非常健壯。
-
其龐大的用戶社區可以爲新用戶提供支持。
-
它的開放源碼許可允許你以任何你想要的方式使用它。
專題學習目錄
ASM 系列詳細教程-04-ASM interface and components 接口和組件
ASM 系列詳細教程-06-ASM method struct 方法結構
ASM 系列詳細教程-09-ASM 方法增強 aop 字節碼實戰
ASM 系列詳細教程-10-ASM metadata 元數據之泛型
ASM 系列詳細教程-11-ASM metadata 元數據之註解 annotation
ASM 系列詳細教程-12-ASM metadata 元數據之調試 debug
ASM 系列詳細教程-13-ASM core api 向後兼容
ASM 系列詳細教程-14-ASM core api 向後兼容守則
ASM 系列詳細教程-15-ASM ReflectASM 入門案例詳細介紹及實戰
ASM 系列詳細教程-16-ASM Tree api 類接口與組件
ASM 系列詳細教程-17-ASM Tree api 類組件組成詳解
ASM 系列詳細教程-18-ASM Tree api 方法接口與組件
ASM 系列詳細教程-19-ASM Tree api 方法組件組成
ASM 系列詳細教程-20-ASM Method 方法分析介紹
ASM 系列詳細教程-21-ASM Method 方法分析接口與組件
ASM 系列詳細教程-22-ASM Metadata 元數據 Generic Annotation Debug
ASM 系列詳細教程-23-ASM Tree API 向後兼容能力
快速入門
jar 引入
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-all</artifactId>
<version>5.1</version>
</dependency>
Hello World
- HelloWorld.java
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.GeneratorAdapter;
import org.objectweb.asm.commons.Method;
import java.io.FileOutputStream;
import java.io.PrintStream;
/**
* <p> </p>
*
* <pre> Created: 2018/7/20 下午2:01 </pre>
* <pre> Project: asm </pre>
*
* @author houbinbin
* @version 1.0
* @since JDK 1.7
*/
public class Bean extends ClassLoader implements Opcodes {
public static void main(final String args[]) throws Exception {
// creates a ClassWriter for the Example public class,
// which inherits from Object
ClassWriter cw = new ClassWriter(0);
cw.visit(V1_1, ACC_PUBLIC, "Example", null, "java/lang/Object", null);
MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null,
null);
mw.visitVarInsn(ALOAD, 0);
mw.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
mw.visitInsn(RETURN);
mw.visitMaxs(1, 1);
mw.visitEnd();
mw = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main",
"([Ljava/lang/String;)V", null, null);
mw.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
"Ljava/io/PrintStream;");
mw.visitLdcInsn("Hello world!");
mw.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println",
"(Ljava/lang/String;)V");
mw.visitInsn(RETURN);
mw.visitMaxs(2, 2);
mw.visitEnd();
byte[] code = cw.toByteArray();
FileOutputStream fos = new FileOutputStream("Example.class");
fos.write(code);
fos.close();
Bean loader = new Bean();
Class exampleClass = loader
.defineClass("Example", code, 0, code.length);
exampleClass.getMethods()[0].invoke(null, new Object[]{null});
// ------------------------------------------------------------------------
// Same example with a GeneratorAdapter (more convenient but slower)
// ------------------------------------------------------------------------
cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
cw.visit(V1_1, ACC_PUBLIC, "Example", null, "java/lang/Object", null);
Method m = Method.getMethod("void <init> ()");
GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, m, null, null,
cw);
mg.loadThis();
mg.invokeConstructor(Type.getType(Object.class), m);
mg.returnValue();
mg.endMethod();
m = Method.getMethod("void main (String[])");
mg = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC, m, null, null, cw);
mg.getStatic(Type.getType(System.class), "out", Type
.getType(PrintStream.class));
mg.push("Hello world!");
mg.invokeVirtual(Type.getType(PrintStream.class), Method
.getMethod("void println (String)"));
mg.returnValue();
mg.endMethod();
cw.visitEnd();
code = cw.toByteArray();
loader = new Bean();
exampleClass = loader.defineClass("Example", code, 0, code.length);
exampleClass.getMethods()[0].invoke(null, new Object[]{null});
}
}
拓展閱讀
更多技術文章,生活趣事,盡在【老馬嘯西風】。
應用實戰
基於 ASM 實現比 Spring BeanUtil.copyProperties 性能更好的拷貝框架