上一篇文章,我们已体验到ASM的威力,那么结合上面的代码解释ASM是怎么执行的。
ClassWriter clazzWriter = new ClassWriter(0);
首先看下官方文档对ClassWriter的描述:
A ClassVisitor that generates classes in bytecode form. More precisely this visitor generates a byte array conforming to the Java class file format. It can be used alone, to generate a Java class "from scratch", or with one or more ClassReader and adapter class visitor to generate a modified class from one or more existing Java classes.
方法的栈长度和本地变量表长度用户自己计算;
clazzWriter.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC, "com/wy/asm/HelloWorld", null, "java/lang/Object", null);
解释下方法中参数的意思:
- Opcodes.V1_6指定类的版本
- Opcodes.ACC_PUBLIC表示这个类是public
- “com/wy/asm/HelloWorld”类的全限定名称
- 第一个null位置变量定义的是泛型签名,
- “java/lang/Object”这个类的父类
- 第二个null位子的变量定义的是这个类实现的接口
String setMethodDesc = "(" + Type.getDescriptor(String[].class) + ")V";
MethodVisitor mv = clazzWriter.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "main",
setMethodDesc, null, null);//新增加一个main方法
mv.visitCode();//启动访问字节码
//在java/lang/System上添加一个Ljava/io/PrintStream类型的字段‘out’
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitLdcInsn("Hello World!");//将常量池中的字符串常量加载到栈顶 ,输出字符串内容
//调用java/io/PrintStream中的println()方法
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
mv.visitInsn(Opcodes.RETURN);//设置返回值
mv.visitMaxs(0, 0);//设置方法的栈和本地变量表的大
mv.visitEnd();//结束访问
代码中的注释,可以让我们看个大概了吧。
上面的代码中我们看到了如何使用ASM生成一个简单的JAVA类,里面使用到了很多的基本概念,比如:方法描述、引用描述等
一、类版本:
一个Java二进制的类文件,都有一个版本,因此ASM中提供了几个常量来指定一个类的版,这些常量定义在org.objectweb.asm.Opcodes接口中,如下:
// versions
int V1_1 = 3 << 16 | 45;
int V1_2 = 0 << 16 | 46;
int V1_3 = 0 << 16 | 47;
int V1_4 = 0 << 16 | 48;
int V1_5 = 0 << 16 | 49;
int V1_6 = 0 << 16 | 50;
int V1_7 = 0 << 16 | 51;
二、JVM内部名字:
在Java二进制文件中使用的是JVM的内部名字,而不是我们所熟悉的以“.”分割的全限定名,内部名字是以“/”替代“.”的全名,例如:java.lang.String在JVM中的内部名字是java/lang/String。在ASM中可以使用org.objectweb.asm.Type类中的静态方法getInternalName(final Class c) 来获得,如下:
public class InternalNameTransform {
public static void main(String[] args) {
System.out.println(Type.getInternalName(String.class));
System.out.println(Type.getInternalName(Integer.class));
System.out.println(Type.getInternalName(InternalNameTransform.class));
}
}
运行结果:
java/lang/String
java/lang/Integer
com/wy/asm/InternalNameTransform
三、类型描述:
我们知道JAVA类型分为基本类型和引用类型,在JVM中对每一种类型都有与之相对应的类型描述,如下表:
Java类型 |
JVM中的描述 |
boolean |
Z |
char |
C |
byte |
B |
short |
S |
int |
I |
float |
F |
long |
J |
double |
D |
Object |
Ljava/lang/Object; |
int |
[I |
Object |
[[Ljava/lang/Object; |
|
在ASM中要获得一个类的JVM内部描述,可以使用org.objectweb.asm.Type类中的getDescriptor(final Class c)方法,如下:
public class TypeDescriptors {
public static void main(String[] args) {
System.out.println(Type.getDescriptor(TypeDescriptors.class));
System.out.println(Type.getDescriptor(String.class));
}
}
运行结果:
Lcom/wy/asm/TypeDescriptors;
Ljava/lang/String;
四、方法描述:
在Java的二进制文件中,方法的方法名和方法的描述都是存储在Constant pool中的,且在两个不同的单元里。因此,方法描述中不含有方法名,只含有参数类型和返回类型,如下:
方法描述,在类中的 |
方法描述,在二进制文件中的 |
void a(int i,float f) |
(IF)V |
void a(Object o) |
(Ljava/lang/Object;)V |
int a(int i,String s) |
(ILjava/lang/String;)I |
int[] a(int[] i) |
([I)[I |
String a() |
()Ljava/lang/String; |
|
获取一个方法的描述可以使用org.objectweb.asm.Type.getMethodDescriptor方法,如下:
public class MethodDescriptors {
public static void main(String[] args) throws Exception {
Method m = String.class.getMethod("substring", int.class);
System.out.println(Type.getMethodDescriptor(m));
}
}
运行结果:
(I)Ljava/lang/String;
其实在org.objectweb.asm.Type类中提供了很多方法。
参考:http://victorzhzh.iteye.com/blog/875644
分享到:
相关推荐
该框架专注于优化和简化ASM(Java Bytecode Engineering Library)的使用,ASM是一个广泛应用于Java字节码操作的库。 asmSupport框架的核心设计思路在于提供一套更为直观和简便的API,这些API能够帮助开发者更加...
7. **asm-3.1.jar**:ASM是一个Java字节码操控和分析框架,常用于动态代理、代码混淆、AOP(面向切面编程)等领域。在RESTful服务中,ASM可能用于运行时动态生成或修改类,以适应特定需求。 总结来说,RESTful.jar...
首先,`hibernage 需要package`这个表述可能是指运行Hibernate应用程序时,需要导入相关的Java包。Hibernate的核心依赖包括但不限于以下这些: 1. **Hibernate核心库**:这是Hibernate的基础,包含了ORM的主要功能...
在`beans.xml`配置文件中声明这个bean,指定其ID和对应的Java类。例如: ```xml <?xml version="1.0" encoding="UTF-8"?> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=...
有很多人用程序来表述爱情,在其中我能看到有Money,有Girl,有一些还涉及到Sex,但是我没有找到Love,我始终相信这世上有一种力量直接来自于爱情,到现在仍然相信。*/ C#(读作C sharp),是Microsoft公司新推出的...