Java-ASM框架学习-修改类的字节码
Tips: ASM使用访问者模式,学会访问者模式再看ASM更加清晰
ClassReader
用于读取字节码,父类是Object
主要作用:
- 分析字节码里各部分内容,如版本、字段等等
- 配合其他Visitor使用
主要使用的方法
public void accept(ClassVisitor classVisitor, int parsingOptions) {
this.accept(classVisitor, new Attribute[0], parsingOptions);
}
// 第一个参数是访问者,第二个参数用于跳过读取字节码的一些信息,常用ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES,跳过没必要的调试和帧信息以缩小大小
如何修改已存在的字节码
通过继承ClassVisitor,重写visitxxx方法,在方法中对访问到的数据进行操作,然后传给下一个ClassVisitor的子类处理(如果有的话)。经过一个或多个ClassVisitor的访问链处理后,传到ClassWriter手里,由ClassWriter生成最终的字节码结果

ClassVisitor方法通过构造函数可以传递下一个Visitor进去,如同链表一样,一个个的形成访问链,最后链接到ClassWriter这个特殊的ClassVisitor里去形成结果
实例
被修改的类
package example;
public class TestClass01 {
public int a;
public int b;
public TestClass01() {
System.out.println("init!!");
}
}
ASM代码
package example.modify;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import java.io.IOException;
import example.modify.clsvisitor.*;
import org.objectweb.asm.Opcodes;
import utils.FileUtils;
public class Test01 {
public static void main(String[] args) throws IOException {
String path = FileUtils.getFilePath("example/sample/TestClass01.class");
FileUtils.writeBytes(path, modifyClass());
}
public static byte[] modifyClass() {
ClassReader cr = null;
try {
cr = new ClassReader("example.TestClass01");
} catch (IOException e) {
e.printStackTrace();
}
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
ClassVisitor cv = new TestClass01Visitor(Opcodes.ASM9, cw);
cr.accept(cv, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
return cw.toByteArray();
}
}
package example.modify.clsvisitor;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Opcodes;
public class TestClass01Visitor extends ClassVisitor {
private String addFieldN = "content";
private boolean flag1 = true;
private String addStaticFieldN = "myID";
private int addStaticFieldV = 100;
private boolean flag2 = true;
private String delFieldN = "b";
public TestClass01Visitor(int api, ClassVisitor classVisitor) {
super(api, classVisitor);
}
/**
* 把java版本改成1.6 全限定名改成sample包下,避免两个同样的类冲突
* @param version
* @param access
* @param name
* @param signature
* @param superName
* @param interfaces
*/
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
super.visit(Opcodes.V1_6, access, "example/sample/TestClass01", signature, superName, interfaces);
}
/**
* 添加两个成员删一个成员
* @param access
* @param name
* @param descriptor
* @param signature
* @param value
* @return
*/
@Override
public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
if (name.equals(delFieldN)) return null;
if (name.equals(addFieldN)) flag1 = false; // 存在就不添加
if (name.equals(addStaticFieldN)) flag2 = false;
return super.visitField(access, name, descriptor, signature, value);
}
@Override
public void visitEnd() {
super.visitField(
Opcodes.ACC_PUBLIC,
this.addFieldN,
"Ljava/lang/String;",
null,
""
);
super.visitField(
Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL,
this.addStaticFieldN,
"I",
null,
this.addStaticFieldV
);
super.visitEnd();
}
}
生成的字节码结果(idea反编译后)

Java-ASM框架学习-修改类的字节码的更多相关文章
- 从Java进程里dump出类的字节码文件
想要查看一些被增强过的类的字节码,或者一些AOP框架的生成类,就需要dump出运行时的Java进程里的字节码. 从运行的java进程里dump出运行中的类的class文件的方法: 用agent att ...
- 浅谈Java反射机制 之 获取类的字节码文件 Class.forName("全路径名") 、getClass()、class
另一个篇:获取 类 的 方法 和 属性(包括构造函数) 先贴上Java反射机制的概念: AVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法: 对于任意一个对象,都能够调用它 ...
- Java-ASM框架学习-从零构建类的字节码
Tips: ASM使用访问者模式,学会访问者模式再看ASM更加清晰 什么是ASM ASM是一个操作Java字节码的类库 学习这个类库之前,希望大家对Java 基本IO和字节码有一定的了解. 高版本的A ...
- Java集合框架(常用类) JCF
Java集合框架(常用类) JCF 为了实现某一目的或功能而预先设计好一系列封装好的具有继承关系或实现关系类的接口: 集合的由来: 特点:元素类型可以不同,集合长度可变,空间不固定: 管理集合类和接口 ...
- Java最重要的21个技术点和知识点之JAVA集合框架、异常类、IO
(三)Java最重要的21个技术点和知识点之JAVA集合框架.异常类.IO 写这篇文章的目的是想总结一下自己这么多年JAVA培训的一些心得体会,主要是和一些java基础知识点相关的,所以也希望能分享 ...
- Java虚拟机JVM学习07 类的卸载机制
Java虚拟机JVM学习07 类的卸载机制 类的生命周期 当Sample类被加载.连接和初始化后,它的生命周期就开始了. 当代表Sample类的Class对象不再被引用,即不可触及时,Class对象就 ...
- Java虚拟机JVM学习04 类的初始化
Java虚拟机JVM学习04 类的初始化 类的初始化 在初始化阶段,Java虚拟机执行类的初始化语句,为类的静态变量赋予初始值. 在程序中,静态变量的初始化有两种途径: 1.在静态变量的声明处进行初始 ...
- Java虚拟机JVM学习02 类的加载概述
Java虚拟机JVM学习02 类的加载概述 类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对 ...
- JVM学习笔记——类加载和字节码技术篇
JVM学习笔记--类加载和字节码技术篇 在本系列内容中我们会对JVM做一个系统的学习,本片将会介绍JVM的类加载和字节码技术部分 我们会分为以下几部分进行介绍: 类文件结构 字节码指令 编译期处理 类 ...
随机推荐
- VS Code环境配置
1.语言配置 2.Node.js安装配置 系统变量中NODE_PATH,变量值为nodejs的安装路径. 用户变量Path包含%NODE_PATH% 如果说通过CMD打开的命令行可以执行node -v ...
- [AGC023D] Go Home 题解
题目传送门 Solution 首先排除掉特殊情况:若 \(S\) 在两侧,肯定会顺序/逆序直接走完,答案就是边界减去出发点. 考虑到若 \(P_1\geq P_n\),那么显然 \(1\) 不到家 \ ...
- git GUI Clients
git GUI Clients Git 自带用于提交 (git-gui) 和浏览 (gitk) 的内置 GUI 工具,但也有一些第三方工具供寻求特定平台体验的用户使用. References Git ...
- Scrum Meeting 0602
零.说明 日期:2021-6-2 任务:简要汇报两日内已完成任务,计划后两日完成任务 一.进度情况 组员 负责 两日内已完成的任务 后两日计划完成的任务 困难 qsy PM&前端 完成后端管理 ...
- Spring Cloud Alibaba 介绍及工程准备
简介 SpringCloud Alibaba是阿里巴巴集团开源的一套微服务架构解决方案. 微服务架构是为了更好的分布式系统开发,将一个应用拆分成多个子应用,每一个服务都是可以独立运行的子工程.其中涵盖 ...
- 局域网(以太网与IEEE 802.3、IEEE 802.11、)
文章转自:https://blog.csdn.net/weixin_43914604/article/details/105016637 学习课程:<2019王道考研计算机网络> 学习目的 ...
- Android DataBinding使用详解
简介 DataBinding是一个自动绑定UI的框架. 使用DataBinding需要在app根目录的build.gradle文件中加入DataBinding配置: android { .... da ...
- 第08课 OpenGL 混合
混合: 在这一课里,我们在纹理的基础上加上了混合,它看起具有透明的效果,当然解释它不是那么容易,当希望你喜欢它. 简单的透明OpenGL中的绝大多数特效都与某些类型的(色彩)混合有关.混色的定义为,将 ...
- vue路由监听和参数监听
1.路由携带数据跳转 routerAction(hideDisplays, data) { switch (hideDisplays) { case "pubAccountMenu" ...
- WPF进阶技巧和实战03-控件(4-基于范围的控件及日期控件)
系列文章链接 WPF进阶技巧和实战01-小技巧 WPF进阶技巧和实战02-布局 WPF进阶技巧和实战03-控件(1-控件及内容控件) WPF进阶技巧和实战03-控件(2-特殊容器) WPF进阶技巧和实 ...