详解Java中的字节码增强技术
作者:深色風信子 发布时间:2022-08-20 06:25:12
标签:Java,字节码,增强
1.字节码增强技术
字节码增强技术就是一类对现有字节码进行修改或者动态生成全新字节码文件的技术。
参考地址
2.常见技术
技术分类 | 类型 |
---|---|
静态增强 | AspectJ |
动态增强 | ASM、Javassist、Cglib、Java Proxy |
3.ASM
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>9.4</version>
</dependency>
ASM Core API可以类比解析XML文件中的SAX方式,不需要把这个类的整个结构读取进来,就可以用流式的方法来处理字节码文件。好处是非常节约内存,但是编程难度较大。然而出于性能考虑,一般情况下编程都使用Core API。在Core API中有以下几个关键类:
技术分类 | 类型 |
---|---|
ClassReader | 用于读取已经编译好的.class文件。 |
ClassWriter | 用于重新构建编译后的类,如修改类名、属性以及方法,也可以生成新的类的字节码文件。 |
Visitor类 | 如上所述,CoreAPI根据字节码从上到下依次处理,对于字节码文件中不同的区域有不同的Visitor,比如用于访问方法的MethodVisitor、用于访问类变量的FieldVisitor、用于访问注解的AnnotationVisitor等。为了实现AOP,重点要使用的是MethodVisitor。 |
3.1 测试 Main
package com.xu.test;
/**
* @author Administrator
*/
public class Main {
public void print() {
System.out.println("ASM");
}
}
3.2 测试 CustomerClassVisitor
package com.xu.test;
import org.apache.commons.lang3.StringUtils;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
/**
* ASM 字节码增强技术
*
* @author Administrator
*/
public class CustomerClassVisitor extends ClassVisitor implements Opcodes {
public CustomerClassVisitor(ClassVisitor api) {
super(ASM9, api);
}
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
cv.visit(version, access, name, signature, superName, interfaces);
}
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
MethodVisitor mv = cv.visitMethod(access, name, descriptor, signature, exceptions);
if (StringUtils.equals("print", name) && mv != null) {
mv = new CustomerMethodVisitor(mv);
}
return mv;
}
class CustomerMethodVisitor extends MethodVisitor implements Opcodes {
public CustomerMethodVisitor(MethodVisitor api) {
super(ASM9, api);
}
@Override
public void visitCode() {
super.visitCode();
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitLdcInsn("start");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
}
@Override
public void visitInsn(int opcode) {
if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) || opcode == Opcodes.ATHROW) {
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitLdcInsn("end");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
}
mv.visitInsn(opcode);
}
}
}
3.3 测试 Test
package com.xu.test;
import java.io.File;
import java.io.FileOutputStream;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
/**
* @author Administrator
*/
public class Test {
public static void main(String[] args) throws Exception {
ClassReader reader = new ClassReader("com/xu/test/Main");
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
// 处理
ClassVisitor visitor = new CustomerClassVisitor(writer);
reader.accept(visitor, ClassReader.SKIP_DEBUG);
// 输出
File file = new File("target\\classes\\com\\xu\\test\\Main.class");
FileOutputStream stream = new FileOutputStream(file);
stream.write(writer.toByteArray());
stream.close();
// 测试
Class<?> cls = Class.forName("com.xu.test.Main");
Main main = (Main) cls.getDeclaredConstructor().newInstance();
main.print();
}
}
来源:https://blog.csdn.net/qq_34814092/article/details/127243802


猜你喜欢
- 首先对Servlet上传文件的简单理解此前,Servlet本身没有对文件上传提供直接的支持,一般需要使用第三方框架来实现,这样就比较麻烦不过
- Struts2 Action/动作动作是Struts2框架的核心,因为他们的任何MVC(模型 - 视图 - 控制器)框架。每个URL将被映射
- 构造http headerprivate static final String URL = "url";private
- 1、题目描述找出数组中重复的数字。在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知
- Mybatis的Dao层实现传统开发方式编写UserDao接口public interface UserDao {  
- 1 问题引入1.1 网络架构模型网络架构模型主要有OSI参考模型和TCP/IP五层模型1.1.1 OSI参考模型OSI(Open Syste
- DOM4可以读取和添加XML文件的属性或者元素读取属性:public static void ReadAttributes() throws
- JDBC操作MySQL在实际的企业级开发环境中,如果数据规模特S别大,此时采用传统的SQL语句去处理的话一般需要分成很多批次处理,而且很容易
- 接触微信支付之前听说过这是一个坑,,,心里已经有了准备。。。我以为我没准跳坑出不来了,没有想到我填上了,调用成功之后我感觉公司所有的同事都是
- 前言emmm… 有个需求,需要根据信息生成svg,因为考虑到样式一致性的问题最终决定有服务端来生成svg。Java提供
- 今天在云和学院学了很多,我这次只能先总结一下C#中的虚方法和抽象的运用。理论:虚方法:用virtual修饰的方法叫
- 首先需要明白一点,只有scop为(singleton)单例类型的Bean,spring才支持循环依赖。scope为(prototype)原型
- 简介一个APP如果没有页面跳转那么是没有灵魂的,页面跳转的一个常用说法就是Navigator,flutter作为一个最为优秀的前端框架,Na
- Guava EventBusEventBus是Guava的事件处理机制,是设计模式中观察者模式(生产/消费者编程模型)的优雅实现。对于事件监
- 在项目中经常要用到将字符串解析成Locale,但是没有一个比较好用的类。java本身提供了3个构造函数,但是实际使用过程中,需要自己解析,比
- 题目:将一个数组逆序输出。代码:import java.util.*;public class lianxi31 {public stati
- 预处理指令这些指令/命令不会转换为可执行代码,但会影响编译过程的各个方面;列如,可以让编译器不编译某一部分代码等。C#中主要的预处理指令#d
- Android 2.3.7.r1 按menu键时会停止录像。改成录像时按menu键不做处理,可做如下修改: 在packages/apps/C
- Java及数据库对日期进行格式化Java对日期进行格式化可使用java.text.SimpleDateFormat示例package com
- 本文实例讲述了Android编程实现自动检测版本及自动升级的方法。分享给大家供大家参考,具体如下:步骤:1.检测当前版本的信息Android