字节码增强技术就是一类对现有字节码进行修改或者动态生成全新字节码文件的技术。本文将通过示例详细说说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();
}
}
到此这篇关于详解Java中的字节码增强技术的文章就介绍到这了,更多相关Java字节码增强内容请搜索编程学习网以前的文章希望大家以后多多支持编程学习网!
沃梦达教程
本文标题为:详解Java中的字节码增强技术
基础教程推荐
猜你喜欢
- Java数据结构之对象比较详解 2023-03-07
- springboot自定义starter方法及注解实例 2023-03-31
- ConditionalOnProperty配置swagger不生效问题及解决 2023-01-02
- java基础知识之FileInputStream流的使用 2023-08-11
- Java实现查找文件和替换文件内容 2023-04-06
- Java实现线程插队的示例代码 2022-09-03
- java实现多人聊天系统 2023-05-19
- Java文件管理操作的知识点整理 2023-05-19
- JDK数组阻塞队列源码深入分析总结 2023-04-18
- Java并发编程进阶之线程控制篇 2023-03-07