使用流程:
1:引入依赖:
implementation 'org.ow2.asm:asm:7.1' implementation 'org.ow2.asm:asm-commons:7.1'
2:想要通过字节码插入代码,使所有的InjectTest方法都加上这两行代码:
long startTime = System.currentTimeMillis();
long endTime = System.currentTimeMillis();
public class InjectTest { public InjectTest(){ } public static void main(String[] args) throws InterruptedException { //long startTime = System.currentTimeMillis(); Thread.sleep(3000L); //long endTime = System.currentTimeMillis(); } void method(){ //long startTime = System.currentTimeMillis();
//long endTime = System.currentTimeMillis(); } }
3:通过Javac InjectTest.java,生成InjectTest.class,再通过Java p -c InjectTest.class,生成字节码文件
public class com.example.jvm.InjectTest { public com.example.jvm.InjectTest(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]) throws java.lang.InterruptedException; Code: 0: invokestatic #2 // Method java/lang/System.currentTimeMillis:()J 3: lstore_1 4: ldc2_w #3 // long 3000l 7: invokestatic #5 // Method java/lang/Thread.sleep:(J)V 10: invokestatic #2 // Method java/lang/System.currentTimeMillis:()J 13: lstore_3 14: return void method(); Code: 0: return }
4:执行以下代码,生成一个替代文件InjectTest2.class:
public class ASMUnitTest { public static void main(String[] args) { try { FileInputStream fileInputStream = new FileInputStream("F:\\Project\\Practice\\Hencoder\\jvm\\src\\main\\java\\com\\example\\jvm\\InjectTest.class"); //获取一个分析器 ClassReader classReader = new ClassReader(fileInputStream); ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES); // 开始插桩 classReader.accept(new MyClassVisitor(Opcodes.ASM7, classWriter), ClassReader.EXPAND_FRAMES); byte[] bytes = classWriter.toByteArray(); FileOutputStream fileOutputStream = new FileOutputStream("F:\\Project\\Practice\\Hencoder\\jvm\\src\\main\\java\\com\\example\\jvm\\InjectTest2.class"); fileOutputStream.write(bytes); fileOutputStream.close(); fileInputStream.close(); }catch (Exception e){ e.printStackTrace(); } } /** * 用来访问类的信息 */ static class MyClassVisitor extends ClassVisitor{ public MyClassVisitor(int api) { super(api); } public MyClassVisitor(int api, ClassVisitor classVisitor) { super(api, classVisitor); } /** * 每读取到一个方法,都会执行这个api */ @Override public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { MethodVisitor methodVisitor = super.visitMethod(access, name,descriptor,signature, exceptions); return new MyMethodVisitor(api, methodVisitor, access, name, descriptor); } } static class MyMethodVisitor extends AdviceAdapter { /** * Constructs a new {@link AdviceAdapter}. * * @param api the ASM API version implemented by this visitor. Must be one of {@link * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}. * @param methodVisitor the method visitor to which this adapter delegates calls. * @param access the method's access flags (see {@link Opcodes}). * @param name the method's name. * @param descriptor the method's descriptor (see {@link Type Type}). */ protected MyMethodVisitor(int api, MethodVisitor methodVisitor, int access, String name, String descriptor) { super(api, methodVisitor, access, name, descriptor); } /** * 方法进去的时候 */ int s; @Override protected void onMethodEnter() { super.onMethodEnter(); //0: invokestatic #2 // Method java/lang/System.currentTimeMillis:()J //是对象,以L开头,以分号结束,()代表的是无参的,J代表的是long类型 invokeStatic(Type.getType("Ljava/lang/System;"),new Method("currentTimeMillis", "()J")); //3: lstore_1 s = newLocal(Type.LONG_TYPE); storeLocal(s); } /** * 方法退出的时候 */ @Override protected void onMethodExit(int opcode) { super.onMethodExit(opcode); // 10: invokestatic #2 // Method java/lang/System.currentTimeMillis:()J //13: lstore_3 } } }
生成的InjectTest2.class文件,把这个InjectTest2.class替换原先的InjectTest.class达到热修复的效果。
public class InjectTest { public InjectTest() { long var1 = System.currentTimeMillis(); } public static void main(String[] var0) throws InterruptedException { long var1 = System.currentTimeMillis(); Thread.sleep(3000L); long var5 = System.currentTimeMillis(); } void method() { long var1 = System.currentTimeMillis(); long var5 = System.currentTimeMillis(); } }
标签:插桩,InjectTest,System,long,class,currentTimeMillis,public,ASM From: https://www.cnblogs.com/wnpp/p/17177611.html