您的位置:首页 > 游戏 > 游戏 > 上海中风险地区_租赁合同模板_网站建设合同模板_网络营销的概述

上海中风险地区_租赁合同模板_网站建设合同模板_网络营销的概述

2024/11/17 3:06:17 来源:https://blog.csdn.net/weixin_47592544/article/details/143424957  浏览:    关键词:上海中风险地区_租赁合同模板_网站建设合同模板_网络营销的概述
上海中风险地区_租赁合同模板_网站建设合同模板_网络营销的概述

在 Android 开发中,ASM 是一个通用的字节码操控和分析框架,它主要用于读取、修改和生成 Java 字节码。ASM 全称为 “Abstract Syntax Manipulation”,可以直接操作 .class 文件,使开发者能够在字节码层面进行性能优化、插桩代码、性能监测和其他操作,而不需要关注 Java 源代码。这在需要动态修改字节码的库(如AOP框架)中非常常用。


    testImplementation("org.ow2.asm:asm:9.6")testImplementation("org.ow2.asm:asm-commons:9.6")

由于是测试模块使用,所以用 testImplementation


创建一个测试类 TestMain:

public class TestMain {public static void main(String[] args) throws InterruptedException {Thread.sleep(1000);}
}

然后使用 javac 把这个这个文件编译成 .class 文件

javac D:\demo\my_demo\app\src\test\java\com\example\my_demo\TestMain.java

这个路径是该文件的全路径(自行替换)

编译好之后该文件路径下就会多出一个 TestMain.class,可以双击点开查看:


假设要对这个 class 文件中的方法加一个耗时打印,则需要在 class 文件中的方法的开头和结尾都加一些逻辑

在执行的 main 方法中:

fun main() {val fis = FileInputStream("D:\\demo\\my_demo\\app\\src\\test\\java\\com\\example\\my_demo\\TestMain.class")val classReader = ClassReader(fis)val classWrite = ClassWriter(ClassWriter.COMPUTE_FRAMES)val classVisitor = object : ClassVisitor(Opcodes.ASM9, classWrite) {// 解析到方法时,回调此函数override fun visitMethod(access: Int, name: String?, descriptor: String?, signature: String?, exceptions: Array<out String>?): MethodVisitor? {val rawVisitMethod = super.visitMethod(access, name, descriptor, signature, exceptions)return MyMethodVisitor(Opcodes.ASM9, rawVisitMethod, access, name, descriptor)}}classReader.accept(classVisitor, 0) // 开始访问 Class 文件// 将新 Class 文件输出val fos = FileOutputStream("D:\\demo\\my_demo\\app\\src\\test\\java\\com\\example\\my_demo\\TestMain2.class")fos.write(classWrite.toByteArray())fos.close()
}

首先拿到 class 文件,通过 ClassReader 和 ClassVisitor 配合使用,解析 class 文件中的内容(方法、字段等信息都会通过接口回调回来)。我们就可以根据回调回来的信息进行手动修改,修改完成后通过 ClassWriter 输出成一个新的 class 文件


自定义的方法修改类 MyMethodVisitor:

class MyMethodVisitor(api: Int, methodVisitor: MethodVisitor?, access: Int, name: String?, descriptor: String?) : AdviceAdapter(api, methodVisitor, access, name, descriptor) {var start = 0// 方法开始时调用override fun onMethodEnter() {super.onMethodEnter()// 插入:long start = System.currentTimeMillis();invokeStatic(Type.getType("Ljava/lang/System;"), Method("currentTimeMillis", "()J"))start = newLocal(Type.LONG_TYPE)storeLocal(start)}// 方法结束时调用override fun onMethodExit(opcode: Int) {super.onMethodExit(opcode)// 插入:long end = System.currentTimeMillis();invokeStatic(Type.getType("Ljava/lang/System;"), Method("currentTimeMillis", "()J"))val end = newLocal(Type.LONG_TYPE)storeLocal(end)// 插入:System.out.println(end - start);getStatic(Type.getType("Ljava/lang/System;"), "out", Type.getType("Ljava/io/Printstream;"))loadLocal(end)loadLocal(start)math(GeneratorAdapter.SUB, Type.LONG_TYPE)invokeVirtual(Type.getType("Ljava/io/Printstream;"), Method("println", "(Ljava/lang/String;)V"))}
}

通过这样子配置后,运行一下 main 方法,就会在路径下多出一个 TestMain2.class 文件,双击点开查看:

这样子通过 ASM 来对 class 文件进行修改和输出成一个新的 class 文件。例子中是对 class 文件中所有的方法都进行插桩了,若只需要特定方法的话,在 ClassVisitor 的回调方法中进行方法名的判断即可


ASM 还可以在构建 APK 过程中结合 Gradle 插件进行使用,从而实现自动化代码修改或增强。例如,在构建 .class 文件时自动插入一些想要的逻辑。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com