`

ASM(一) 初识ASM

 
阅读更多

 

一、什么是ASM

      首先看下官方中的说明 ASM a very small and fast Java bytecode manipulation framework。

ASM是一个JAVA字节码分析、创建和修改的开源应用框架。它可以动态生成二进制格式的stub类或其他代理类,或者在类被JAVA虚拟机装入内存之前,动态修改类。在ASM中提供了诸多的API用于对类的内容进行字节码操作的方法。与传统的BCEL和SERL不同,在ASM中提供了更为优雅和灵活的操作字节码的方式。ASM相当小巧,并且它有更高的执行效率,是BCEL的7倍,SERP的11倍以上(摘自网络,具体没有测试)。目前ASM已被广泛的开源应用架构所使用,例如:Spring、Hibernate等。

二、ASM能做什么

      我们都知道,一般情况下,Class文件是通过javac编译器产生的,然后通过类加载器加载到虚拟机内,再通过执行引擎去执行。现在我们可以通过ASM的API直接生成符合Java虚拟机规范的Class字节流,这样,ASM做的事情一定程度上正是javac解释器做的工作。

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

     那么,我们就可以通过ASM来实现诸如代码生成,代码混淆,代码转换等等以字节码为操作目标的工作。

三、ASM大体结构

 

四、Java二进制(class)文件的格式

     要想驾驭ASM,先要了解一下JAVA的CLASS文件格式。JAVA的CLASS文件通常是树型结构。根节点包含以下元素:

  • ConstantPool:符号表;
  • FieldInfo:类中的成员变量信息;
  • MethodInfo:类中的方法描述;
  • Attribute:可选的附加节点。

      FieldInfo节点包含成员变量的名称,诸如public,private,static等的标志。

      ConstantValue属性用来存储静态的不变的成员变量的值。

      Deprecated和Synthetic被用来标记一个成员变量是不被推荐的或由编译器生成的。

      MethodInfo节点包含方法的名称,参数的类型和和它的返回值,方法是公有的,私有的或静态的等标志。

      MethodInfo包含可选的附加属性,其中最重要的是Code属性,它包含非抽象的方法的代码。

      Exceptions属性包含方法将抛出的Exception的名称。

      Deprecated和Synthetic属性的信息同上面的FieldInfo的定义一样。

 

      根节点的可选属性有SourceFile,InnerClasses和Deprecated。

      SourceFile用来存储被编译成字节码的源代码文件的原始名称;

      InnerClasses存储内部类的信息。由于这些属性的存在,java 的类格式是可以扩展的,也就是说可以在一个class中 附加一些非标准的属性, java虚拟机会忽略这些不可识别的属性,正常的加载这个class。

 

ConstantPool是一个由数字或字符串常量的索引组成的队列,或由此类的树的其他节点引用的,由其他对象创建的被引用常量的索引组成的队列。这个表的目标是为了减少冗余。例如,FieldInfo节点不包含节点的名称,只包含它在这一表中的索引。同样的,GETFIELD和PUTFIELD不直接包含成员变量的名称,只包含名称的索引。

 

五、体验ASM的威力

     相信我们还记得学习Java的第一个例子 HelloWorld.java,那么我们就用ASM生成我们的第一个字节文件 HelloWorld.class。

1、现将代码给出,然后逐步解释:

package com.wy.asm;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

/**
 * ASM
 * 
 * @author wy
 * 
 */
public class AsmGenerateCar {
	public void generateClass() {
		//
		ClassWriter clazzWriter = new ClassWriter(0);
		clazzWriter.visit(Opcodes.V1_6, Opcodes.ACC_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);
		mv.visitCode();
		mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
		mv.visitLdcInsn("Hello World!");
		mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");  
		mv.visitInsn(Opcodes.RETURN);
		mv.visitMaxs(0, 0);
		mv.visitEnd();
		
		//
		byte[] classFile = clazzWriter.toByteArray();
		clazzWriter.visitEnd();
		
		//
		try {
			String path = Thread.currentThread().getContextClassLoader()
					.getResource("").getPath().replaceAll("%20", " ");
			FileOutputStream fos = new FileOutputStream(new File(path + "com/wy/asm/HelloWorld.class"));
			try {
				fos.write(classFile);
				fos.flush();
				fos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}

		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
		}

	}

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

}
 

执行上面的代码会在目录下生成我们想要的字节文件,来张图片验证:


2、使用反编译工具Java Decompiler 

  • 大小: 16.5 KB
  • 大小: 26 KB
  • 大小: 37.7 KB
分享到:
评论

相关推荐

    01 - 初识Java ASM - 简书1

    2022/2/22 下午4:26舍是境界. .. 字数 阅读螺杆式真空泵h5制作软件linux服务器linux培训班克真空泵免备案服务器关注ASM是什么简单来说

    自己动手写操作系统

    4.1.6 整理boot.asm142 4.2 保护模式下的"操作系统"144 第5章 内核雏形146 5.1 用NASM在Linux下写Hello World146 5.2 再进一步,汇编和C同步使用148 5.3 ELF(Executable and Linkable Format)150 5.4 从Loader...

    深入JVM内核 - 原理、诊断与优化

    初识JVM JVM分类 Java语言规范 JVM规范 介绍JVM的基本知识和发展历史,并介绍了Java语言规范和JVM规范。 第二课 JVM运行机制简介 堆、栈、方法区等 JVM启动流程 内存模型和volatile实例 解释和编译运行的概念 介绍...

    自己动手写操作系统 电子工业出版社 pdf

    4.1.6 整理boot.asm142 4.2 保护模式下的“操作系统”144 第5章 内核雏形146 5.1 用NASM在Linux下写Hello World146 5.2 再进一步,汇编和C同步使用148 5.3 ELF(Executable and Linkable Format)150 5.4 从Loader到...

    自己动手写操作系统 pdf

    4.1.6 整理boot.asm142 4.2 保护模式下的“操作系统”144 第5章 内核雏形146 5.1 用NASM在Linux下写Hello World146 5.2 再进一步,汇编和C同步使用148 5.3 ELF(Executable and Linkable Format)150 5.4 从Loader到...

    自己动手写操作系统(含源代码).part2

    有关操作系统的书籍资料可以找到很多,但是关注如何帮助读者实现一个试验性操作系统的书籍却不多见,本书便是从一个简单的引导扇区开始,讲述一个操作系统成长的故事,以作读者参考之用。 本书面向实践,通过具体...

    自己动手写操作系统(含源代码).part1

    有关操作系统的书籍资料可以找到很多,但是关注如何帮助读者实现一个试验性操作系统的书籍却不多见,本书便是从一个简单的引导扇区开始,讲述一个操作系统成长的故事,以作读者参考之用。 本书面向实践,通过具体...

    vld(Visual Leak Detector 内存泄露检测工具 源码)

    初识Visual Leak Detector  灵活自由是C/C++语言的一大特色,而这也为C/C++程序员出了一个难题。当程序越来越复杂时,内存的管理也会变得越加复杂,稍有不慎就会出现内存问题。内存泄漏是最常见的内存问题之一。...

    集群好书《高性能Linux服务器构建实战》 试读章节下载

    2.3.2 配置一个简单的Varnish实例 2.3.3 Varnish对应多台Web服务器的配置实例 2.4 运行Varnish 2.4.1 varnishd指令 2.4.2 配置Varnish运行脚本 2.4.3 管理Varnish运行日志 2.5 管理Varnish 2.5.1 ...

    完全掌握加密解密实战超级手册.zip02

    1034.2.1 反汇编和调试工具W32Dasm 1034.2.2 国产静态反编译工具C32asm 1144.2.3 反汇编工具IDA Pro 1164.3 实战静态分析解密 1274.3.1 如何实现静态分析解密 1274.3.2 汇编指令及其机器码值 1284.3.3 判断真假注册...

    完全掌握加密解密实战超级手册.z01

    网络客户端程序补丁 2288.2.1 程序拦截的验证代码 2288.2.2 增加自动修改机器号功能 2298.2.3 用补丁修改程序 2328.2.4 为程序附带一个动态链接库 2348.2.5 用补丁加密可执行文件 2358.3 代码自修改SMC技术 2388.3.1...

Global site tag (gtag.js) - Google Analytics