`
victorzhzh
  • 浏览: 203011 次
  • 来自: ...
社区版块
存档分类
最新评论

ASM系列之一:初探ASM

阅读更多

一、什么是ASM

    ASM是一个JAVA字节码分析、创建和修改的开源应用框架。在ASM中提供了诸多的API用于对类的内容进行字节码操作的方法。与传统的BCEL和SERL不同,在ASM中提供了更为优雅和灵活的操作字节码的方式。目前ASM已被广泛的开源应用架构所使用,例如:Spring、Hibernate等。

二、ASM能干什么

    分析一个类、从字节码角度创建一个类、修改一个已经被编译过的类文件

三、ASM初探例子

    这里我们使用ASM的CoreAPI(ASM提供了两组API:Core和Tree,Core是基于访问者模式来操作类的,而Tree是基于树节点来操作类的)创建一个MyClass类,目标类如下:

public class MyClass {
	private String name;
	
	public Myclass(){
		this.name = "zhangzhuo";
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

 这个类在构造方法中初始化了属性name,并提供了两个public方法来修改和访问name属性。

 

 接下来就要书写创建这个类的代码了,现将代码给出,然后逐步解释,代码如下:

   代码1:

public class GenerateClass {
	public void generateClass() {

                //方法的栈长度和本地变量表长度用户自己计算
		ClassWriter classWriter = new ClassWriter(0);	
	
                //Opcodes.V1_6指定类的版本
                //Opcodes.ACC_PUBLIC表示这个类是public,
                //“org/victorzhzh/core/classes/MyClass”类的全限定名称
                //第一个null位置变量定义的是泛型签名,
                //“java/lang/Object”这个类的父类
                //第二个null位子的变量定义的是这个类实现的接口
classWriter.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC,
				"org/victorzhzh/core/classes/MyClass", null,
				"java/lang/Object", null);
               
		ClassAdapter classAdapter = new MyClassAdapter(classWriter);

		classAdapter.visitField(Opcodes.ACC_PRIVATE, "name",
				Type.getDescriptor(String.class), null, null);//定义name属性

		classAdapter.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null,
				null).visitCode();//定义构造方法

		String setMethodDesc = "(" + Type.getDescriptor(String.class) + ")V";
		classAdapter.visitMethod(Opcodes.ACC_PUBLIC, "setName", setMethodDesc,
				null, null).visitCode();//定义setName方法

		String getMethodDesc = "()" + Type.getDescriptor(String.class);
		classAdapter.visitMethod(Opcodes.ACC_PUBLIC, "getName", getMethodDesc,
				null, null).visitCode();//定义getName方法

		byte[] classFile = classWriter.toByteArray();//生成字节码

		MyClassLoader classLoader = new MyClassLoader();//定义一个类加载器
		Class clazz = classLoader.defineClassFromClassFile(
				"org.victorzhzh.core.classes.MyClass", classFile);
		try {//利用反射方式,访问getName
			Object obj = clazz.newInstance();
			Method method = clazz.getMethod("getName");
                        System.out.println(obj.toString());
			System.out.println(method.invoke(obj, null));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	class MyClassLoader extends ClassLoader {
		public Class defineClassFromClassFile(String className, byte[] classFile)
				throws ClassFormatError {
			return defineClass(className, classFile, 0, classFile.length);
		}
	}

	public static void main(String[] args) {
		GenerateClass generateClass = new GenerateClass();
		generateClass.generateClass();
	}
}

   代码2:

public class MyClassAdapter extends ClassAdapter {

	public MyClassAdapter(ClassVisitor cv) {
		super(cv);
	}

	@Override
	public MethodVisitor visitMethod(int access, String name, String desc,
			String signature, String[] exceptions) {
		MethodVisitor methodVisitor = cv.visitMethod(access, name, desc,
				signature, exceptions);
		if (name.equals("<init>")) {
			return new InitMethodAdapter(methodVisitor);
		} else if (name.equals("setName")) {
			return new SetMethodAdapter(methodVisitor);
		} else if (name.equals("getName")) {
			return new GetMethodAdapter(methodVisitor);
		} else {
			return super.visitMethod(access, name, desc, signature, exceptions);
		}
	}

        //这个类生成具体的构造方法字节码
	class InitMethodAdapter extends MethodAdapter {
		public InitMethodAdapter(MethodVisitor mv) {
			super(mv);
		}

		@Override
		public void visitCode() {
			mv.visitVarInsn(Opcodes.ALOAD, 0);
			mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object",
					"<init>", "()V");//调用父类的构造方法
			mv.visitVarInsn(Opcodes.ALOAD, 0);
			mv.visitLdcInsn("zhangzhuo");//将常量池中的字符串常量加载刀栈顶
			mv.visitFieldInsn(Opcodes.PUTFIELD,
					"org/victorzhzh/core/classes/MyClass", "name",
					Type.getDescriptor(String.class));//对name属性赋值
			mv.visitInsn(Opcodes.RETURN);//设置返回值
			mv.visitMaxs(2, 1);//设置方法的栈和本地变量表的大小
		}
	};

        //这个类生成具体的setName方法字节码	
        class SetMethodAdapter extends MethodAdapter {
		public SetMethodAdapter(MethodVisitor mv) {
			super(mv);
		}

		@Override
		public void visitCode() {
			mv.visitVarInsn(Opcodes.ALOAD, 0);
			mv.visitVarInsn(Opcodes.ALOAD, 1);
			mv.visitFieldInsn(Opcodes.PUTFIELD,
					"org/victorzhzh/core/classes/MyClass", "name",
					Type.getDescriptor(String.class));
			mv.visitInsn(Opcodes.RETURN);
			mv.visitMaxs(2, 2);
		}

	}

       
         //这个类生成具体的getName方法字节
        class GetMethodAdapter extends MethodAdapter {

		public GetMethodAdapter(MethodVisitor mv) {
			super(mv);
		}

		@Override
		public void visitCode() {
			mv.visitVarInsn(Opcodes.ALOAD, 0);
			mv.visitFieldInsn(Opcodes.GETFIELD,
					"org/victorzhzh/core/classes/MyClass", "name",
					Type.getDescriptor(String.class));//获取name属性的值
			mv.visitInsn(Opcodes.ARETURN);//返回一个引用,这里是String的引用即name
			mv.visitMaxs(1, 1);
		}
	}
}

   运行结果:

org.victorzhzh.core.classes.MyClass@1270b73
zhangzhuo

   这个例子只是简单地介绍了一下ASM如何创建一个类,接下来的几个章节,将详细介绍ASM的CoreAPI和TreeAPI中如何操作类。

 

分享到:
评论
1 楼 wzx_it 2015-11-20  
   你就是牛人,联系方式留一个啊

相关推荐

    初探ASM

    【ASM初探】 ASM是一个Java字节码操控和分析框架,它可以直接生成和修改Java类和.dex文件。这个强大的工具广泛应用于动态代码生成、代理、混淆、性能优化等领域。ASM库的设计目标是小且高效,使得它成为Java字节码...

    asm.rar_arm

    《汇编语言初探——以ARM架构为例》 在计算机科学的世界里,汇编语言作为底层编程的一种形式,是理解计算机工作原理的关键。本资源"asm.rar_arm"聚焦于ARM架构下的汇编语言学习,旨在为初学者提供一个入门的平台。...

    AVR指令与汇编系统

    AVR指令与汇编系统是微控制器领域中的一个重要概念,主要针对的是Atmel公司的AVR系列8位单片机,这些单片机采用RISC(Reduced Instruction Set Computer)架构,与传统的CISC(Complex Instruction Set Computer)...

    Linux核心初探.pdf

    【Linux核心初探】 Linux操作系统的核心是开源世界的重要组成部分,为开发者提供了深入理解操作系统底层机制的机会。这篇文档主要探讨了Linux内核的组织结构以及如何阅读和理解内核代码。 Linux内核源码的顶层目录...

    DSP280x_CodeStartBranch.rar_CodeStartBranch_c2000

    在"DSP280x_CodeStartBranch.asm"文件中,我们可以看到一系列针对C2000 DSP280x系列的初始化步骤。首先,该代码会设置堆栈指针SP,这是处理器运行时管理内存的重要数据结构。然后,它会进行复位处理,清零或初始化...

    开发一个最简单的操作系统

    - **大小**:一个合法的引导扇区通常包含512个字节。 - **结束标志**:引导扇区必须以0xAA55结束,这是一个特定的十六进制数值,用于标识扇区的合法性。 - **剩余空间处理**:引导扇区中的实际执行代码可能少于510...

    电子-jpstm32asmfirst.zip

    《电子-jpstm32asmfirst.zip:STM32汇编语言编程初探》 STM32系列微控制器是基于ARM Cortex-M内核的高性能、低功耗微处理器,广泛应用于单片机和嵌入式系统设计。在这个压缩包中,我们重点关注的是STM32的汇编语言...

    2013年中国数据库大会PPT第一部分

    第一部分包含: 1.大数据革命.pdf 2.MPP NewSQL 数据库集群支撑企业超大规模数据仓库案例介绍.pdf 3.Big Data in Action – 企业如何运用微软 Big Data 的技术具体规划并落实运行.pdf 4.小米hadoop/hbase微实践.pdf ...

    x86 汇编语言 银行系统

    《x86汇编语言:银行系统初探》 在计算机科学的世界里,汇编语言是一种底层编程语言,它与机器代码紧密相连,是程序员直接操控硬件的重要工具。本资源聚焦于x86架构下的汇编语言,通过一个简单的银行系统实例,为...

    2013中国数据库大会ppt(1)

    MySQL Cluster实战初探 .pdf SAP HANA深度剖析.pdf eXtremeDB内存数据库性能提升方案分享.pdf 运用之妙 存乎一心—— Oracle优化器案例与算法解析.pdf DM7 MPP架构——同时满足OLAP与OLTP需求.pdf SAP 让大数据飞翔....

    2013中国数据大会ppt(2)

    MySQL Cluster实战初探 .pdf SAP HANA深度剖析.pdf eXtremeDB内存数据库性能提升方案分享.pdf 运用之妙 存乎一心—— Oracle优化器案例与算法解析.pdf DM7 MPP架构——同时满足OLAP与OLTP需求.pdf SAP 让大数据飞翔....

    2013中国数据库大会ppt(3)

    MySQL Cluster实战初探 .pdf SAP HANA深度剖析.pdf eXtremeDB内存数据库性能提升方案分享.pdf 运用之妙 存乎一心—— Oracle优化器案例与算法解析.pdf DM7 MPP架构——同时满足OLAP与OLTP需求.pdf SAP 让大数据飞翔....

    AndroidAnimationExercise:Android动画的各种实现,包括帧动画,补间动画和属性动画的总结分享

    随着时间的推移,里面积累的很多代码,大致用5个片段进行分类:扫一扫体验: ImitateFragment(模仿三方应用特效)仿新浪微博雷达扫描效果和卡片动画效果( )仿简书长按生成图片效果沉寝式模式初探仿简书头部...

Global site tag (gtag.js) - Google Analytics