ASM 可以在类被加载入 JVM 之前动态修改已存在类行为,也可以直接生成 .class 字节码文件。...核心类: ClassReader:读取字节码并将其转换为内部数据结构。 ClassWriter:将内部数据结构转换回字节码,允许对字节码进行修改。...CoreAPI 根据字节码结构从上到下依次处理,对于字节码文件中不同的区域有不同的 Visitor,比如用于访问方法的 MethodVisitor、用于访问类变量的 FieldVisitor、用于访问注解的...ASM Tree API ASM Tree API 是 ASM 框架提供的一种基于树结构的字节码访问方式。将字节码文件读取到内存中构建树结构,通过各种 Node 类来映射字节码。...asm-tree.jar 主要类按“包含”组织关系: ClassNode:(类) VisitMethod(): 用于访问类中的方法。 VisitField(): 用于访问类中的字段。
而一般我们在使用asm的时候,我们都只会操作Class文件,然后根据class的文件名+路径对其进行一次简单的判断,当前类是不是我们需要做插桩或者扫描操作的,然后我们会读取这个文件byte数组,之后在完成...如果byte数组非空的情况下,代表当前类被进行了字节码修改操作,然后我们只要把这个文件进行一次覆盖操作就可以了。...ClassNode简介 如果你仔细读了关于字节码的文章后,你应该会知道Java中当一个方法被调用时会产生一个栈帧(Stack Frame),可以理解为那个方法被包含在了这个栈帧里,栈帧包括3个部分,局部变量区...(srcClass) //1 将读入的字节转为classNode classReader.accept(classNode, 0) classNodeMap...) val classWriter = ClassWriter(0) //3 将classNode转为字节数组 classNode.accept(classWriter
但是字节码如果我们直接操作,成本太大,并且效率也不高。这个时候你就需要一款利器,将字节码转换成java语言,从而你就可以随心所欲的操纵字节码。...而这里我要介绍的就是操作字节码的一把利器-ASM,ASM是一个java字节码操纵框架,它能被用来动态生成类或者增强既有类的功能。...Java class 被存储在严格格式定义的 .class文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性以及 Java 字节码(指令)。...ASM从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够根据用户要求生成新类。 ASM的优点如下: 有一个简单的模块API,设计完善,使用方便。...,甚至可以生成新的类的字节码文件。
而一般我们在使用asm的时候,我们都只会操作Class文件,然后根据class的文件名+路径对其进行一次简单的判断,当前类是不是我们需要做插桩或者扫描操作的,然后我们会读取这个文件byte数组,之后在完成...如果byte数组非空的情况下,代表当前类被进行了字节码修改操作,然后我们只要把这个文件进行一次覆盖操作就可以了。...ClassNode简介 如果你仔细读了关于字节码的文章后,你应该会知道Java中当一个方法被调用时会产生一个栈帧(Stack Frame),可以理解为那个方法被包含在了这个栈帧里,栈帧包括3个部分,局部变量区...= ClassNode(ASM5) val classReader = ClassReader(srcClass) //1 将读入的字节转为classNode...) val classWriter = ClassWriter(0) //3 将classNode转为字节数组 classNode.accept(classWriter
ASM的TreeApi 对于Method的转换、生成也提供了一系列的组件和接口。 MethodNode中大多数属性和方法都和ClassNode类似,其中最主要的属性就是InsnList了。...InsnList是一个双向链表对象,包含了存储方法的字节指令序。先来看下InsnList中的主要是属性和方法。...AbstractInsnNode数组存储了字节码指令对象的链表连接关系。AbstractInsnNode是一个抽象父类,代表了字节指令的一个抽象类。AbstractInsnNode的主要方法如下。...Java代码 package asm.tree.method; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Opcodes...当然,这个链表结构也维系了整个字节码指令的结构。
添加和删除类成员 添加和删除类就是在ClassNode对象的fields或methods列表中添加或删除元素 public class ClassTransformer { protected...比如有一个转换,要向一个类中添加注释,包含其内容的数字签名,就属于上述情景。...类的生成和转化 上面只是如何创建和转换 ClassNode 对象,但还没有看到如何由一个类的字节数组表示来构造一个 ClassNode,或者反过来,由 ClassNode 构造这个字节数组。...MethodNode 对象,却还没有看到与类的字节数组表示进行链接。...API 仅用于方法,将核心 API 用于类。
java.io.IOException; 6 import java.io.OutputStream; 7 import java.util.Scanner; 8 9 /* 10 * 文件字节输出流...1.给出输出流的目的地 12 * 2.创建指向目的地的输出流 13 * 3.人输出流把数据写入到目的地 14 * 4.关闭输出流 15 * 16 * 举例: 使用文件输出流写文件...a.txt 17 * 措施:首先使用具有刷新功能的构造方法创建指向文件a.txt的输出流, 18 * 并向a.txt文件写入“新年快乐”,然后在选择使用不刷新文件的构造方法 19 * 20...并向文件写入(即尾加),"happy New Year !"。..."); 54 //a.txt的大小:22字节 55 out.close(); 56
,便将封装它的操作码替换为一个新的 VarInsnNode 操作码,这个新操作码封装了 “ALOAD 1” 字节码, 将原程序中 将值设为16 替换为 将值设为局部变量1。...ASM 的 MethodVisitor 提供了一种 hook(钩子)机制,以便能够访问方法中的每一个操作码,这样我们便能够对字节码文件进行细粒度地修改。...只有 visit 这个方法一定会被调用一次,因为它 获取了类头部的描述信息 **ASM Core API 类似于解析 XML 文件中的 SAX 方式,直接用流式的方法来处理字节码文件,而不需要把这个类的整个结构读进内存之中...2)、ClassWriter:用于重新构建编译后的类,如修改类名、属性以及方法,也可以生成新的类的字节码文件。...3)、各种 Visitor 类:如上所述,Core API 根据字节码从上到下依次处理,对于字节码文件中不同的区域有不同的 Visitor,比如用于访问方法的 MethodVisitor、用于访问类变量的
,之后将堆栈信息写入文件。...如何将这部分不讲武德的三方sdk的线程池构造也调整了呢? 这次也还是使用asm吧,之前我们在使用asm的时候大部分场景都是采取新增一个函数调用的方式。这次我们将采取类替换的规则。...: ByteArray { val classNode = ClassNode(Opcodes.ASM5) val classReader = ClassReader(srcClass...) //1 将读入的字节转为classNode classReader.accept(classNode, 0) //2 对classNode的处理逻辑...转为字节数组 classNode.accept(classWriter) return classWriter.toByteArray() } private
因为我们首先要取到的是R文件,然后把R文件的内容收集起来,之后再去所有有使用到R文件的类中,所以如果使用正常的Transform流程的话这个可能就没办法操作了....然后通过文件或者类信息进行增量编译的缓存数据,因为在增量编译得时候我们需要对上次的R文件进行一次记录,否则增量情况下就会出现缺失的问题。这部分尤其容易发生在路由表增量的过程中。...我们在这个过程中只收集我们所需要的数据信息,当然这次操作我们不会进行任何的asm替换操作和文件写入操作,只会将文件转化成asm语法相关的。当然这里是用tree api还是core api就随便了。...api 'org.ow2.asm:asm:9.2' api 'org.ow2.asm:asm-tree:9.2' 第二次asm操作的时候我们会进行文件copy操作以及类替换等等,第二次的时候我们会在第一次收集到的类数据的...,之后将原来要做的类替换或者方法替换等还原出来。
这些其实都是.class文件,因为已经跳过了javac的过程,所以也就没有语法树了。...很相似,因为已经编译成字节码了,而lint也是使用tree api,可以看到很多老熟人,比如ClassNode,MethodNode,还是一点点分析吧。...其中INVOKEVIRTUAL,INVOKESTATIC 都是MethodInsnNode,所以我们只要在getApplicableAsmNodeTypes方法中添加AbstractInsnNode.METHOD_INSN...然后我们需要做的也很简单,因为我们的输入类型只有MethodInsnNode,所以当checkInstruction就是栈帧调用方法被执行的时候,将call直接转化成MethodInsnNode,之后判断当前栈判断当前方法是不是操作符...当然理解文章内容的前提是你要有一定的虚拟机机器码的认知,对于asm相关的理解就会融汇贯通,无论是transform还是ClassScanner就都是一样的。
,最后也没有成功,而且Transform Action的输入产物都是单一文件,修改也是针对单一文件的,所以貌似也不完全是一个很好的替换方案,之前文章介绍的那种复杂的asm操作则无法负荷了。...然后我们构造一个ClassReader实例,然后将byte数组传入,之后调用classReader.accept方法,之后我们就能在visitor中逐个访问数据了。...这就是新的asm api 的设计思路了,也是我们这边大佬的字节码框架大佬的设计。另外bytex内的设计思路也是如此。...class PrivacyClassNode(private val nextVisitor: ClassVisitor) : ClassNode(Opcodes.ASM5) { override...second } 这部分比较简单,把逻辑抽象定义在类ClassNode内,然后在visitEnd方法的时候调用我之前说的accept(nextVisitor)方法。
大家好我是小悦,之前的文章我们介绍了字节码的基础知识,今天我们将介绍字节码相关的应用场景,首先要介绍的是如何对字节码做解析和修改,本文将会详细给大家介绍一个工业级字节码操作框架 ASM。...ASM 当我们需要对一个 class 文件做修改时,我们可以选择自己解析这个class 文件,在符合 Java 字节码规范的前提下进行字节码改造。...ASM 操作字节码案例 接下面我们用几个简单的例子来演示 ASM 各个核心类操作字节码的案例。...访问类的方法和字段 ASM 的 visitor 设计模式可以很方便的用来访问类文件中我们感兴趣的部分,比如类文件的字段和方法列表,有下面的类: public class MyMain { public...,经常会需要给类新增一个字段存储额外的信息,在 ASM 中给类新增一个字段非常简单,以下面的 MyMain 类为例,使用 javac 编译为 class 文件。
这里我将字节码增强技术分两点来说,也是我认为实现字节码增强需要解决的两个关键点: 1.字节码是为了机器设计的,而非人类,字节码可读性极差、修改门槛极高,那么我们如何修改字节码呢?...Javassist ByteBuddy ByteKit 性能 ASM的性能最高,因为它直接操作字节码,没有中间环节 劣于ASM 介于javassist和ASM之间 介于javassist和ASM之间...void redefineClasses(ClassDefinition... definitions) 用给定的类的字节码数组替换指定的类的字节码文件,也就是重新定义指定的类 void retransformClasses...2.根据加载的插件做字节码增强。3.使用JMTP将服务和插件产生的数据(trace、指标等)进行上报。...,通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将 5.1 多线程traceId丢失问题 pfinder目前已经将traceId放到了MDC中,我们通过在日志配置文件中添加
在以下章节中你可以学习到如下知识; Java Agent 非硬编码式代理类,这也就是常说的探针技术 ASM 字节码编程简单使用 工程打包额外加载其他 jar 方法 最后是一个破解演示,仅适合个人学习使用...ASM 介绍 ASM 是一个 JAVA 字节码分析、创建和修改的开源应用框架。在 ASM 中提供了诸多的API用于对类的内容进行字节码操作的方法。...然后使用 new VarInsnNode(Opcodes.ALOAD, 1) 将本地指定的引用存入栈中 之后将我们的入参内容直接返回,new InsnNode(Opcodes.ARETURN),从方法中返回引用类型的数据...这个时候虽然你大爷还是你大爷,但你大娘已经不是你大娘了 为了测试的验证我们将变更后的字节码代码(大娘)输出到工程目录下,也就是一个 class 文件,下文测试时候验证 4....比如监控,调试等 别忘了我们还在 Agent 中输出了新的字节码,看看这个时候的类是什么样(你大爷还是你大爷,但你大娘可不是你大娘了) 被代理前 public class DecodeCertificates
Java字节码,里面演示了如何将字节码反过来解析出对应的class文件。....一方面是小端排列,另一方面需要寻址.最重要的一点是,class文件的类索引里面所有的信息都是直接排进去的,但是dex文件里面的类都是存的索引,dex文件更为紧凑.也就是意味着,如果需要修改dex文件,...下面简单介绍一下ASM ASM 库提供了两个用于生成和转换已编译类的 API,一个是核心 API,以基于事件的形式来表示类,另一个是树 API,以基于对象的形式来表示类。...基于对象的 API 提供了一种方法,可以将表示一个类的事件序列转换为表示同一个类的对象树,也可以反过来,将对象树表示为等价的事件序列。换言之,基于对象的 API 构建在基于事件的 API 之上。...核心是ClassNode,可以在此基础上增加或者删除属性,成员之类的,当然还有更高级的。缺点是:如果使用者对字节码不熟悉的话不好操作 3.掌握插桩应该具备的基础知识 (1)熟练掌握字节码相关技术。
Groovy 脚本中定义的所有 Groovy 类 ; 使用 each 方法遍历上述 Class 类节点集合 List classes , 在闭包中 , 使用 it 获取正在遍历的..., 并进行遍历 // 在 ModuleNode 中的类节点封装在了如下成员中 // List classes = new LinkedList<ClassNode..., 并进行遍历 // 在 ModuleNode 中的类节点封装在了如下成员中 // List classes = new LinkedList<ClassNode..., 在文件中配置 ASTTransformation 实现类的全类名 : MyASTTransformation 3、使用命令行进行编译时处理 首先 , 进入 Y:\002_WorkSpace\003...MyASTTransformation.groovy , 将编译后的字节码文件 MyASTTransformation.class 保存到 Y:\002_WorkSpace\003_IDEA\Groovy_Demo2
, 在MyASTTransformation#visit 方法中 , 首先获取了 ModuleNode , 然后查找指定的 ClassNode , 从指定的 ClassNode 中查找对应的 MethodNode..., 并进行遍历 // 在 ModuleNode 中的类节点封装在了如下成员中 // List classes = new LinkedList<ClassNode..., 在文件中配置 ASTTransformation 实现类的全类名 : MyASTTransformation 3、使用命令行进行编译时处理 首先 , 进入 D:\002_Project\012_...MyASTTransformation.groovy , 将编译后的字节码文件 MyASTTransformation.class 保存到 D:\002_Project\012_Groovy\Groovy_Demo...\src\main\groovy\classes 目录下 , groovyc -d classes MyASTTransformation.groovy 再后 , 打包上述编译好的字节码文件 , 存放在
ASTTransformation#visit 方法简介 ---- 在上一篇博客 【Groovy】编译时元编程 ( 编译 ASTTransformation | 打包 ASTTransformation 字节码文件...* 编译时处理方法 * @param nodes AST 抽象语法树节点 , 是 ASTNode 数组类型 * @param source 源单元 , 可以通过该对象拿到源文件...> classes = new LinkedList(); 成员表示该脚本中定义了多少个 Groovy 类节点 ; private List methods...; 通过 ModuleNode 类 , 可以拿到 Groovy 脚本中几乎所有的内容 ; org.codehaus.groovy.ast.ModuleNode 原型如下 : /** * 表示一个模块,...该模块通常由一个类声明组成, * 但可以包括一些导入、一些语句和多个类, * 这些类与Python或Ruby中的脚本等语句混合在一起 * * @author Jochen Theodorou
类加载器 二、完整代码示例 三、执行结果 四、博客资源 前言 ---- 在 上一篇博客 【Android 逆向】启动 DEX 字节码中的 Activity 组件 ( DEX 文件准备 | 拷贝资源目录下的文件到内置存储区...的类加载器 , 就可以成功加载 DEX 文件了 , 该操作类似于热修复 ; /** * 不修改类加载器的前提下 , 运行 Dex 字节码文件中的组件 * * @param...// 替换 LoadedApk 中的 类加载器 ClassLoader // 然后使用替换的类加载器加载 DEX 字节码文件中的 Activity 组件...类加载器 ClassLoader , 然后使用替换的类加载器加载 DEX 字节码文件中的 Activity 组件 ; 完整代码示例 : package com.example.classloader_demo...// 替换 LoadedApk 中的 类加载器 ClassLoader // 然后使用替换的类加载器加载 DEX 字节码文件中的 Activity 组件 if (Build.VERSION.SDK_INT
领取专属 10元无门槛券
手把手带您无忧上云