ASM 字节码增强框架详解

  • Attribute类:字节码中属性的类抽象。

  • ByteVector类:字节码二进制存储的容器。

  • Opcodes接口:字节码指令的一些常量定义。

  • Type类:类型相关的常量定义以及一些基于其上的操作。

类图关系


ClassReader是ASM中最核心的实现,它用于读取并解析Class字节码

在构建ClassReader实例时,它首先保存字节码二进制数组b,然后创建items数组,数组的长度在字节码数组的第8、9个字节指定(最前面4个字节是魔数CAFEBABE,之后2个字节是次版本号,再后2个字节是主版本号),每个item表示常量池项在字节码数组的偏移量加1(常量池中每个项由1个字节的type和紧跟的字节数组表示,常量池项有12种类型,其中CONSTANT_FieldRef_Info、CONSTANT_MethodRef_Info、CONSTANT_InterfaceMethodRef_Info、CONSTANT_NameAndType_Info包括其类型字节占用5个字节,另外4个字节每2个字节为字段、方法等所在的类、其名称、描述符在当前常量池中CONSTANT_Utf8_Info类型的引用;CONSTANT_Integer_Info、CONSTANT_Float_Info包括其类型字节占用5个字节,另外四个字节为其对应的值;CONSTANT_Class_Info、CONSTANT_String_Info包括其类型字节占用3个字节,另外两个字节为在当前常量池CONSTANT_Utf8_Info项的索引;CONSTANT_Utf8_Info类型第1个字节表示类型,第2、3个字节为该项所表示的字符串的长度);CONSTANT_Double_Info、CONSTANT_Long_Info加类型字节为9个字;maxStringLength表示最长的UTF8类型的常量池项的值,用于决定在解析CONSTANT_Utf8_Info类型项时最大需要的字符数组;header表示常量池之后的字节码的第一个字节。

ASM 开发

=====================================================================

IDEA使用插件 asm outline 查看 asm 如何生成该类。

  • 类实现

对应的 asm 编程代码

package asm.com.javaedge.asm;

import java.util.*;

import org.objectweb.asm.*;

public class TestAsmDump implements Opcodes {

public static byte[] dump() throws Exception {

ClassWriter cw = new ClassWriter(0);

FieldVisitor fv;

MethodVisitor mv;

AnnotationVisitor av0;

cw.visit(52, ACC_PUBLIC + ACC_SUPER, “com/javaedge/asm/TestAsm”, null, “java/lang/Object”, null);

cw.visitSource(“TestAsm.java”, null);

{

mv = cw.visitMethod(ACC_PUBLIC, “”, “()V”, null, null);

mv.visitCode();

Label l0 = new Label();

mv.visitLabel(l0);

mv.visitLineNumber(7, l0);

mv.visitVarInsn(ALOAD, 0);

mv.visitMethodInsn(INVOKESPECIAL, “java/lang/Object”, “”, “()V”, false);

mv.visitInsn(RETURN);

Label l1 = new Label();

mv.visitLabel(l1);

mv.visitLocalVariable(“this”, “Lcom/javaedge/asm/TestAsm;”, null, l0, l1, 0);

mv.visitMaxs(1, 1);

mv.visitEnd();

}

{

mv = cw.visitMethod(ACC_PUBLIC, “m”, “()V”, null, null);

mv.visitCode();

Label l0 = new Label();

Label l1 = new Label();

Label l2 = new Label();

mv.visitTryCatchBlock(l0, l1, l2, “java/lang/InterruptedException”);

Label l3 = new Label();

mv.visitLabel(l3);

mv.visitLineNumber(10, l3);

mv.visitFieldInsn(GETSTATIC, “java/lang/System”, “out”, “Ljava/io/PrintStream;”);

mv.visitLdcInsn(“Hello ASM”);

mv.visitMethodInsn(INVOKEVIRTUAL, “java/io/PrintStream”, “println”, “(Ljava/lang/String;)V”, false);

mv.visitLabel(l0);

mv.visitLineNumber(12, l0);

mv.visitLdcInsn(new Long(100L));

mv.visitMethodInsn(INVOKESTATIC, “java/lang/Thread”, “sleep”, “(J)V”, false);

mv.visitLabel(l1);

mv.visitLineNumber(15, l1);

Label l4 = new Label();

mv.visitJumpInsn(GOTO, l4);

mv.visitLabel(l2);

mv.visitLineNumber(13, l2);

mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[]{“java/lang/InterruptedException”});

mv.visitVarInsn(ASTORE, 1);

Label l5 = new Label();

mv.visitLabel(l5);

mv.visitLineNumber(14, l5);

mv.visitVarInsn(ALOAD, 1);

mv.visitMethodInsn(INVOKEVIRTUAL, “java/lang/InterruptedException”, “printStackTrace”, “()V”, false);

mv.visitLabel(l4);

mv.visitLineNumber(16, l4);

mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);

mv.visitInsn(RETURN);

Label l6 = new Label();

mv.visitLabel(l6);

mv.visitLocalVariable(“e”, “Ljava/lang/InterruptedException;”, null, l5, l4, 1);

mv.visitLocalVariable(“this”, “Lcom/javaedge/asm/TestAsm;”, null, l3, l6, 0);

mv.visitMaxs(2, 2);

mv.visitEnd();

}

cw.visitEnd();

return cw.toByteArray();

}

}

看看最简单的统计方法执行时间

mv.visitMethodInsn(INVOKESTATIC, “java/lang/System”, “currentTimeMillis”, “()J”, false);

mv.visitVarInsn(LSTORE, 1);

mv.visitFieldInsn(GETSTATIC, “java/lang/System”, “out”, “Ljava/io/PrintStream;”);

mv.visitLdcInsn(“Hello ASM”);

mv.visitMethodInsn(INVOKEVIRTUAL, “java/io/PrintStream”, “println”, “(Ljava/lang/String;)V”, false);

mv.visitLabel(l0);

mv.visitLineNumber(13, l0);

mv.visitLdcInsn(new Long(100L));

mv.visitMethodInsn(INVOKESTATIC, “java/lang/Thread”, “sleep”, “(J)V”, false);

mv.visitLabel(l1);

mv.visitLineNumber(16, l1);

Label l5 = new Label();

mv.visitJumpInsn(GOTO, l5);

mv.visitLabel(l2);

mv.visitLineNumber(14, l2);

mv.visitFrame(Opcodes.F_FULL, 2, new Object[]{“com/javaedge/asm/TestAsm”, Opcodes.LONG}, 1, new Object[]{“java/lang/InterruptedException”});

mv.visitVarInsn(ASTORE, 3);

Label l6 = new Label();

mv.visitLabel(l6);

mv.visitLineNumber(15, l6);

mv.visitVarInsn(ALOAD, 3);

mv.visitMethodInsn(INVOKEVIRTUAL, “java/lang/InterruptedException”, “printStackTrace”, “()V”, false);

mv.visitLabel(l5);

mv.visitLineNumber(17, l5);

mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);

mv.visitMethodInsn(INVOKESTATIC, “java/lang/System”, “currentTimeMillis”, “()J”, false);

mv.visitVarInsn(LSTORE, 3);

Label l7 = new Label();

mv.visitLabel(l7);

mv.visitLineNumber(18, l7);

mv.visitFieldInsn(GETSTATIC, “java/lang/System”, “out”, “Ljava/io/PrintStream;”);

mv.visitTypeInsn(NEW, “java/lang/StringBuilder”);

mv.visitInsn(DUP);

mv.visitMethodInsn(INVOKESPECIAL, “java/lang/StringBuilder”, “”, “()V”, false);

mv.visitLdcInsn("m\u65b9\u6cd5\u6267\u884c\u65f6\u95f4: ");

mv.visitMethodInsn(INVOKEVIRTUAL, “java/lang/StringBuilder”, “append”, “(Ljava/lang/String;)Ljava/lang/StringBuilder;”, false);

mv.visitVarInsn(LLOAD, 3);

mv.visitVarInsn(LLOAD, 1);

mv.visitInsn(LSUB);

mv.visitMethodInsn(INVOKEVIRTUAL, “java/lang/StringBuilder”, “append”, “(J)Ljava/lang/StringBuilder;”, false);

mv.visitMethodInsn(INVOKEVIRTUAL, “java/lang/StringBuilder”, “toString”, “()Ljava/lang/String;”, false);

mv.visitMethodInsn(INVOKEVIRTUAL, “java/io/PrintStream”, “println”, “(Ljava/lang/String;)V”, false);

Label l8 = new Label();

mv.visitLabel(l8);

mv.visitLineNumber(19, l8);

mv.visitInsn(RETURN);

Label l9 = new Label();

mv.visitLabel(l9);

mv.visitLocalVariable(“e”, “Ljava/lang/InterruptedException;”, null, l6, l5, 3);

最后

我还为大家准备了一套体系化的架构师学习资料包以及BAT面试资料,供大家参考及学习

已经将知识体系整理好(源码,笔记,PPT,学习视频)

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

new Label();

mv.visitLabel(l9);

mv.visitLocalVariable(“e”, “Ljava/lang/InterruptedException;”, null, l6, l5, 3);

最后

我还为大家准备了一套体系化的架构师学习资料包以及BAT面试资料,供大家参考及学习

已经将知识体系整理好(源码,笔记,PPT,学习视频)

[外链图片转存中…(img-VFU6y3R5-1721131262138)]

[外链图片转存中…(img-WKiYFVqG-1721131262138)]

[外链图片转存中…(img-4YNvQIjk-1721131262139)]

  • 15
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值