`

ASM(二) - Java类的基本表述

 
阅读更多

上一篇文章,我们已体验到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-util.jar

    asm-util-1.3.4.jar, asm-util-1.3.5.jar, asm-util-1.4.1.jar, asm-util-1.4.3.jar, asm-util-1.5.1.jar, asm-util-1.5.2.jar, asm-util-1.5.3.jar, asm-util-2.0.jar, asm-util-2.1.jar, asm-util-2.2.1-sources....

    asm-all-5.0.2-API文档-中文版.zip

    赠送jar包:asm-all-5.0.2.jar; 赠送原API文档:asm-all-5.0.2-javadoc.jar; 赠送源代码:asm-all-5.0.2-sources.jar; 赠送Maven依赖信息文件:asm-all-5.0.2.pom; 包含翻译后的API文档:asm-all-5.0.2-javadoc-...

    asm-all-5.2.jar

    asm-all-5.2.jar asm-all-5.2.jar asm-all-5.2.jar asm-all-5.2.jar asm-all-5.2.jar asm-all-5.2.jar asm-all-5.2.jar asm-all-5.2.jar asm-all-5.2.jar asm-all-5.2.jar asm-all-5.2.jar asm-all-5.2.jar asm-all-...

    asm4-guide.pdf

    ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class 文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性...

    asm-2.2.3.jar,asm-commons-2.2.3.jar,asm-util-2.2.3.jar,cglib-nodep-2.1_3.jar

    2. asm-commons-2.2.3.jar:这个组件包含了ASM的一些通用工具和辅助类,例如类访问器、注解处理器等,方便开发者处理更复杂的字节码操作场景。 3. asm-util-2.2.3.jar:该库提供了一些实用工具,如堆栈映射表的处理...

    asm-2.2.3.jar,asm-commons-2.2.3.jar,asm-util-2.2.3.jar

    1. **asm-2.2.3.jar**:这是ASM框架的核心模块,提供了基本的字节码操作和分析功能。它包括了对Java类和方法的低级别访问,允许开发者创建、修改和分析类的字节码。这个模块包含了访问者模式,使得遍历和修改类结构...

    asm.jar各个版本

    asm-1.3.3.jar, asm-1.3.4.jar, asm-1.3.5.jar, asm-1.4.1.jar, asm-1.4.2.jar, asm-1.4.3.jar, asm-1.4.jar, asm-1.5.1.jar, asm-1.5.2.jar, asm-1.5.3.jar, asm-2.0.jar, asm-2.1.jar, asm-2.2.1-sources.jar, asm...

    asm-9.1-API文档-中文版.zip

    赠送jar包:asm-9.1.jar; 赠送原API文档:asm-9.1-javadoc.jar; 赠送源代码:asm-9.1-sources.jar; 赠送Maven依赖信息文件:asm-9.1.pom; 包含翻译后的API文档:asm-9.1-javadoc-API文档-中文(简体)版.zip; ...

    asm-4.2-API文档-中文版.zip

    赠送jar包:asm-4.2.jar; 赠送原API文档:asm-4.2-javadoc.jar; 赠送源代码:asm-4.2-sources.jar; 赠送Maven依赖信息文件:asm-4.2.pom; 包含翻译后的API文档:asm-4.2-javadoc-API文档-中文(简体)版.zip; ...

    redhat/centos6.9 kmod-oracleasm/oracleasm-support/oracleasm rpm包

    kmod-oracleasm-2.0.8-15.el6_9.x86_64 oracleasm-support-2.1.8-1.el6.x86_64 oracleasmlib-2.0.4-1.el6.x86_64 安装顺序: rpm -ivh kmod-oracleasm-2.0.8-15.el6_9.x86_64.rpm rpm -ivh oracleasm-support-2.1.8...

    asm-all-3.0.jar等jar包

    资源包含asm-all-3.0.jar等jar包,可以解决程序中因asm版本引起的兼容性错误。其他相关的jar如下: asm-all-3.0.jar asm-2.2.3.jar asm.jar asm-attrs.jar asm-commons-2.2.3.jar asm-util-2.2.3.jar

    xbean-asm5-shaded-4.4.jar

    xbean-asm5-shaded-4.4.jar

    asm-util-6.0.jar

    asm-util-6.0.jar 编写工具测试类中用到,配合asm-6.0.jar使用

    asm-2.2.1-sources.jar.zip

    1. "asm-2.2.1-sources.jar" - 这是ASM库的源代码,包含了所有类的.java文件,可供开发者阅读和研究。 2. "asm-2.2.1.jar.license.txt" - 这个文件通常包含软件的许可协议,告知用户如何合法地使用ASM库。遵守这些...

    asm-commons-2.2.1-sources.jar.zip

    总的来说,"asm-commons-2.2.1-sources.jar.zip"是一个包含ASM Commons库源代码的压缩文件,对于Java开发者,特别是对字节码操作感兴趣的开发者来说,这个资源非常有价值。通过研究源代码,开发者可以学习到字节码...

    asm-analysis-5.0.3.jar

    asm-analysis-5.0.3.jar;asm-analysis-5.0.3.jar;asm-analysis-5.0.3.jar

    asm-commons-3.3.1.jar

    asm-commons-3.3.1.jar

    asm-commons

    asm-commons-2.0.jar, asm-commons-2.1.jar, asm-commons-2.2.1-sources.jar, asm-commons-2.2.1.jar, asm-commons-2.2.2-sources.jar, asm-commons-2.2.2.jar, asm-commons-2.2.3.jar, asm-commons-2.2.jar, asm-...

    asm-3.3,asm-commons-3.3,asm-tree-3.3.jar

    struts2.3开发依赖的asm包.不然有以下报错java.lang.NoClassDefFoundError: com/opensymphony/xwork2/util/finder/ClassFinder$InfoBuildingVisitor,导入asm-3.3.jar,asm-commons-3.3,asm-tree-3.3.jar即可

    cglib-2.2.jar asm-tree.jar asm-commons.jar asm.jar

    【描述】"cglib动态代理模式jar包 cglib-2.2.jar asm-tree.jar asm-commons.jar asm.jar" 指出,这些jar文件是CGlib库的一部分,它是一个强大的、高性能的代码生成库,广泛用于创建Java动态代理和增强现有类。...

Global site tag (gtag.js) - Google Analytics