另一篇介绍文  https://www.cnblogs.com/clds/p/4985893.html

转载自https://www.cnblogs.com/onlysun/p/4533798.html

Java 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来实现诸如代码生成,代码混淆,代码转换等等以字节码为操作目标的工作

三、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(hello world):

package com.sunchao.asm;

import java.io.File;
import java.io.FileOutputStream; import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes; /**
* the hello world byte code generate
* by asm.
* @author Administrator
*
*/
public class HelloWorld { public static void main(String args[]) throws Exception {
ClassWriter classWriter = new ClassWriter(0);
String className = "com/sunchao/asm/HelloWorld";
classWriter.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC, className, null,
"java/lang/Object", null); MethodVisitor initVisitor = classWriter.visitMethod(Opcodes.ACC_PUBLIC, "<init>",
"()V", null, null);
initVisitor.visitCode();
initVisitor.visitVarInsn(Opcodes.ALOAD, 0);
initVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>",
"V()");
initVisitor.visitInsn(Opcodes.RETURN);
initVisitor.visitMaxs(1, 1);
initVisitor.visitEnd(); MethodVisitor helloVisitor = classWriter.visitMethod(Opcodes.ACC_PUBLIC, "sayHello",
"()V;", null, null);
helloVisitor.visitCode();
helloVisitor.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out",
"Ljava/io/PrintStream;");
helloVisitor.visitLdcInsn("hello world!");
helloVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream",
"println", "(Ljava/lang/String;)V");
helloVisitor.visitInsn(Opcodes.RETURN);
helloVisitor.visitMaxs(1, 1);
helloVisitor.visitEnd(); classWriter.visitEnd();
byte[] code = classWriter.toByteArray();
File file = new File("D:\\HelloWorld.class");
FileOutputStream output = new FileOutputStream(file);
output.write(code);
output.close();
} }

ams入门了解的更多相关文章

  1. [zz]LyX 入门教程

    http://blog.sina.com.cn/s/blog_630e5dec0100w3jl.html The LyX Tutorial by the LyX Team 1 目录 Chapter 1 ...

  2. 【LaTeX】E喵的LaTeX新手入门教程(3)数学公式

    昨天熄灯了真是坑爹.前情回顾[LaTeX]E喵的LaTeX新手入门教程(1)准备篇 [LaTeX]E喵的LaTeX新手入门教程(2)基础排版上一期测试答案1.大家一开始想到的肯定是\LaTeX{}er ...

  3. 【LaTeX】E喵的LaTeX新手入门教程(1)准备篇

    昨天熄灯了真是坑爹.前情回顾[LaTeX]E喵的LaTeX新手入门教程(1)准备篇 [LaTeX]E喵的LaTeX新手入门教程(2)基础排版上一期测试答案1.大家一开始想到的肯定是\LaTeX{}er ...

  4. 【LaTeX】E喵的LaTeX新手入门教程(3)

    [LaTeX]E喵的LaTeX新手入门教程(3) 数学公式作者: 郭英东.sty 昨天熄灯了真是坑爹.前情回顾 [LaTeX]E喵的LaTeX新手入门教程(1)准备篇 [LaTeX]E喵的LaTeX新 ...

  5. Angular2入门系列教程7-HTTP(一)-使用Angular2自带的http进行网络请求

    上一篇:Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数 感觉这篇不是很好写,因为涉及到网络请求,如果采用真实的网络请求,这个例子大家拿到手估计还要自己写一个web ...

  6. ABP入门系列(1)——学习Abp框架之实操演练

    作为.Net工地搬砖长工一名,一直致力于挖坑(Bug)填坑(Debug),但技术却不见长进.也曾热情于新技术的学习,憧憬过成为技术大拿.从前端到后端,从bootstrap到javascript,从py ...

  7. Oracle分析函数入门

    一.Oracle分析函数入门 分析函数是什么?分析函数是Oracle专门用于解决复杂报表统计需求的功能强大的函数,它可以在数据中进行分组然后计算基于组的某种统计值,并且每一组的每一行都可以返回一个统计 ...

  8. Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数

    上一篇:Angular2入门系列教程5-路由(一)-使用简单的路由并在在路由中传递参数 之前介绍了简单的路由以及传参,这篇文章我们将要学习复杂一些的路由以及传递其他附加参数.一个好的路由系统可以使我们 ...

  9. Angular2入门系列教程5-路由(一)-使用简单的路由并在在路由中传递参数

    上一篇:Angular2入门系列教程-服务 上一篇文章我们将Angular2的数据服务分离出来,学习了Angular2的依赖注入,这篇文章我们将要学习Angualr2的路由 为了编写样式方便,我们这篇 ...

随机推荐

  1. MIT 6.828 | JOS | 关于虚拟空间和物理空间的总结

    Question: 做lab过程中越来越迷糊,为什么一会儿虚拟地址是4G 物理地址也是4G ,那这有什么作用呢? 解决途径: 停下来,根据当前lab的进展,再回头看上学期操作系统的ppt & ...

  2. java容器源码分析及常见面试题笔记

      概览 容器主要包括 Collection 和 Map 两种,Collection 存储着对象的集合,而 Map 存储着键值对(两个对象)的映射表. List Arraylist: Object数组 ...

  3. springboot + mybatisPlus 入门实例 入门demo

    springboot + mybatisPlus 入门实例 入门demo 使用mybatisPlus的优势 集成mybatisplus后,简单的CRUD就不用写了,如果没有特别的sql,就可以不用ma ...

  4. J20航模遥控器开源项目系列教程(二)使用说明 | 遥控器制作完成了,怎么用?

    我们的开源宗旨:自由 协调 开放 合作 共享 拥抱开源,丰富国内开源生态,开展多人运动,欢迎加入我们哈~ 和一群志同道合的人,做自己所热爱的事! 项目开源地址:https://github.com/C ...

  5. MySQL数据库中查询数据库表、字段总数量,查询数据总量

    最近要查询一些数据库的基本情况,由于以前用oracle数据库比较多,现在换了MySQL数据库,就整理了一部分语句记录下来. 1.查询数据库表数量 #查询MySQL服务中数据库表数据量 SELECT C ...

  6. Vue企业级优雅实战-00-开篇

    从2018.1.开始参与了多个企业的中台建设,这些中台的技术选型几乎都是基于 Spring Cloud 微服务架构 + 基于 Vue 全家桶的前端.我前后端架构及开发我几乎各占一半的精力,在企业级前端 ...

  7. LR与LR?

    目录 逻辑回归与线性回归 逻辑回归 1.建立目标函数 2. 梯度求解 3. 实现 线性回归 1. 建立目标函数 2. 求解 3. 实现 逻辑回归与交叉熵 逻辑回归与线性回归 逻辑回归 线性回归 目标函 ...

  8. 接口测试 Mock 实战 | 结合 jq 完成批量化的手工 Mock

    本文霍格沃兹测试学院学员学习实践笔记. 一.应用背景 因为本章的内容是使用jq工具配合完成,因此在开始部分会先花一定的篇幅介绍jq机器使用,如果读者已经熟悉jq,可以直接跳过这部分. 先来看应用场景, ...

  9. jQuery源码分析系列(一)初识jQuery

    一个工厂 (function(global, factory){ "use strict" // operation_1 })(typedef window !== "u ...

  10. 传统servelt项目之分页操作

    需求说明: • 演示最终分页效果 • 提供分页素材     • 分页的作用 • 数据量大,一页容不下 • 后台查询部分数据而不是全部数据 • 降低带宽使用,提高访问速度     • 分页的实现思路 • ...