Java Agent与ASM字节码介绍

2023-11-14

Java Agent

Java Agent是jdk1.5以后引入的,也叫做Java代理。

javaAgent是运行方法之前的拦截器。我们利用javaAgent和ASM字节码技术,在JVM加载class二进制文件的时候,利用ASM动态的修改加载的class文件,在监控的方法前后添加计时器功能,用于计算监控方法耗时,同时将方法耗时及内部调用情况放入处理器,处理器利用栈先进后出的特点对方法调用先后顺序做处理,当一个请求处理结束后,将耗时方法轨迹和入参map输出到文件中,然后根据map中相应参数或耗时方法轨迹中的关键代码区分出我们要抓取的耗时业务。最后将相应耗时轨迹文件取下来,转化为xml格式并进行解析,通过浏览器将代码分层结构展示出来,方便耗时分析.

Java Agent是运行在main方法之前的拦截器,它内定的方法名叫premain,也就是说要先执行premain再执行main方法。

利用Java Agent和ASM字节码结束可以在JVM加载class文件的时候,利用ASM动态的修改已经加载的class文件。

Java Agent探针工具特点:

1、支持方法执行耗时范围抓取,根据耗时范围抓取
2、抓取特定的代码配置
3、支持入口方法参数输出功能
4、提供web页面接口耗时、代码调用关系

Java Agent支持目标JVM启动时加载,也支持在目标JVM运行时加载,这两种不同的加载模式会使用不同的入口函数,如果需要在目标JVM启动的同时加载Agent,那么可以选择实现下面的方法

public static void premain(String agentArgs, Instrumentation inst); 
public static void premain(String agentArgs);

JVM将首先寻找[1],如果没有发现[1],再寻找[2]。

启动时修改主要是在jvm启动时,执行native函数的Agent_OnLoad方法,在方法执行时,执行如下步骤:

• 创建InstrumentationImpl对象
• 监听ClassFileLoadHook事件
•调用InstrumentationImpl的loadClassAndCallPremain方法,在这个方法里会去调用javaagent里MANIFEST.MF里指定的Premain-Class类的premain方法

JVMTI全称JVM Tool Interface,是JVM暴露出来的一些供用户扩展的接口集合,JVMTI是基于事件驱动的,也就是JVM每执行到一定的逻辑时就会调用一些事件的回调接口(如果回调接口存在),这些接口就可以被开发者扩展自己的逻辑。

JPLISAgent:全称为Java programming Language Instrumatation Service Agent。
在这里插入图片描述

如果希望在目标JVM运行时加载Agent,则需要实现下面的方法:

public static void agentmain(String agentArgs, Instrumentation inst); 
public static void agentmain(String agentArgs);

运行时修改主要是通过jvm的attach机制来请求目标jvm加载对应的agent,执行native函数的Agent_OnAttach方法,在方法执行时,执行如下步骤:

• 创建InstrumentationImpl对象
• 监听ClassFileLoadHook事件
•调用InstrumentationImpl的loadClassAndCallAgentmain方法,在这个方法里会去调用javaagent里MANIFEST.MF里指定的Agentmain-Class类的agentmain方法

在这里插入图片描述

这两组方法的第一个参数AgentArgs是随同 “–javaagent”一起传入的程序参数,如果这个字符串代表了多个参数,就需要自己解析这些参数。inst是Instrumentation类型的对象,是JVM自动传入的,我们可以拿这个参数进行类增强等操作(可以用于获取JVM信息。)。

/**
 * @author chenTom
 *
 *
 */
public class AgentTest {
    /**
     * 在类加载前执行Agent时首先调用Instrumentation中的addTransformer方法进行注册,
     * 注册参数为ClassFileTransformer对象,然后实现ClassFileTransformer中的transform方法,
     * 在该方法中对要加载的类的字节码做一些处理。
     * @param agentArgs
     * @param inst
     */
    public static void premain(String agentArgs, Instrumentation inst){
        System.out.println("==========================进入premain方法==========================");
        inst.addTransformer(new ClassFileTransformer() {
            @Override
            public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
                //todo logic
                return new byte[0];
            }
        });
    }
}
public interface ClassFileTransformer {
    byte[]
    transform(  ClassLoader         loader,
                String              className,
                Class<?>            classBeingRedefined,
                ProtectionDomain    protectionDomain,
                byte[]              classfileBuffer)
        throws IllegalClassFormatException;
}

ASM

asm是字节码增强技术,通过asm可以生成新的class文件,也可以动态的修改即将要装载入jvm的类信息。

ASM是一个Java字节码操控框架,它被用来动态生成类或者增强已有类的功能。

ASM可以直接生产二进制class文件,也可以在类被加载到Java虚拟机之前动态改变类。Java类存储在.class文件中,ASM就从这些类文件中读入信息,然后可以动态改变类行为、分析类行为、或者生成新类。

ASM字节码增强技术主要是用反射的时候提升性能,如果单纯用jdk的反射调用,性能是比较低的,而使用字节码增强技术后反射的调用时间已经基本可以与直接调用相当了。

反射为什么性能低:

  • 1、Class.forname()调用本地方法,比较耗时
  • 2、Class.getMethod会遍历类的方法。

ASM框架的核心类有以下几个:

ClassReader:该类用来解析编译过的class字节码
ClassWriter:该类用来重新构建编译后的类,比如修改类名,属性以及方法,甚至可以生成新的类的字节码文件。
ClassAdapter:该类实现了ClassVisitor接口,它将对它的方法调用委托给另一个ClassVisitor对象。

因此可以将ASM理解为对类文件的CRUD,经过CRUD的字节码可以转换为类。

ASM的解析类似于SAX解析XML文件,相比于其它方式比如CGLIB,它的优势在于性能更高,在Spring中都是使用的cglib动态代理,而cglib本身就是使用ASM。

利用ASM可以获得class文件的详细信息:比如类名、父类名、接口、成员名、方法参数名、局部变量名、元数据等。
还可以对class文件进行动态修改,比如增加、删除、修改某个类的方法。

CGLIB是对ASM的封装,简化ASM的操作,降低ASM的使用门槛。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java Agent与ASM字节码介绍 的相关文章

  • 自己动手写操作系统第二章 pmtest1.asm分析

    34 pm inc 34 描述符 Usage Descrptor Base Limit Attr Base dd Limit dd Low 20 bits available Attr dw lower 4 bits of higher b
  • KEIL ARM 6.12 compiler 编译__ASM 错误的解决方法

    1 问题 KEIL compiler 设置为 use default compiler version 5 可以正确编译以下汇编和C混合代码 xff0c 更改编译器为V6 12后不识别 ASM关键字 xff0c 并对汇编语法报错 替换为 A
  • 关于make zImage时出现include/asm/timex.h:15:28: asm/arch/timex.h: No such file or directory

    root 64 localhost linux cd linux 2 6 18 root 64 localhost linux 2 6 18 make zImage CHK include linux version h SYMLINK i
  • ASM汇编常用跳转指令-极速查

    作者 xff1a 逆向驿站 微信公众号 xff1a 逆向驿站 知乎 xff1a 逆向驿站 若不是老鸟 xff0c 是不是经常为各种JXX汇编跳转指令查资料 xff1f 影响效率 xff0c 更影响潜意识整体分析的 34 灵光一现 34 本公
  • vs 出现chkstk.asm问题的解决方式

    程序编译成功无报错 xff0c 执行debug时 xff0c 突然系统跳chkstk asm 报了堆栈错误 定位问题 我们到堆栈最后执行的地方 xff0c 发现是一个线程创建 这里肯定没有问题 xff0c 那么问题肯定出现在线程的初始化里
  • Gradle 插件 + ASM 实战 - JVM 虚拟机加载 Class 原理

    开篇就提到效能优化涉及的范围会很广 xff0c 考虑后面需要经常用到 asm 字节码插桩 xff0c 我们首先从 Gradle 插件 43 ASM 实战 开始讲 xff0c 但又希望大家能知其然也知其所以然 xff0c 因此我们首先得讲下
  • Android使用ASM修改函数

    目录 参考文章 Android 编译插桩 xff08 一 xff09 xff1a ASM https github com yxhuangCH CSLearn blob master android Android 20 E7 BC 96
  • 从利用Arthas排查线上Fastjson问题到Java动态字节码技术(中)

    上一篇文章 中通过对一次线上事故的复盘 引出了福报厂的Arthas 一个建立在Java动态字节码技术之上的Java诊断工具 关于Arthas的使用方式就不赘述了 查看官方文档可以很快上手 玩法也特别多 上一篇中也仅仅只介绍了一种使用场景 即
  • 2 如何用ASM进行插桩

    假如我们现在有这样一个文件 代码如下 public class Hello public String name hello public static void main String args System out println He
  • 汇编寄存器介绍

    1 通用寄存器 名称 全称 32位 16位 8位 编号 功能 rax 累加器 Accumulator eax ax ah al 0 0000 返回值 rcx 计数器 Count Register ecx cx ch cl 1 0001 第二
  • AOP的底层实现--ASM

    在ASM的核心组件中 Opcodes接口定义了一些常量 尤其是版本号 访问标识符 字节码等信息 ClassReader用于读取Class文件 它的作用时进行Class文件的解析 并可以接受一个ClassVisitor ClassReader
  • asm常用命令汇总

    在Oracle 环境下 使用grid帐号执行 运行asmcmd进入asm命令模式 如 grid oradb node1 asmcmd ASMCMD gt ASMCMD gt du 显示指定的ASM目录下ASM文件占用的所有磁盘空间 ASMC
  • 汇编语言中各种寄存器的总结

    汇编语言中各种寄存器的总结 1 通用寄存器 数据寄存器 AX BX CX DX 指针寄存器 SP BP 变址寄存器 SI DI 2 控制寄存器 IP FLAG 3 段寄存器 CS 代码段寄存器 基本概念解释 start作用 DS 数据段寄存
  • 【8086汇编】字符串逆序的实现,附代码

    目录 引言 题目 程序思想 程序例程 程序结果 改进思路 引言 之前有本科的同学需要做一个汇编程序 简单补了补发现自己会嘻嘻嘻 题目 题目 从键盘输入任一字符串 字符数 gt 1 在下一行以相反的次序显示出来 如 输入字符串123abc 在
  • Linux系统调用指南

    Linux系统调用指南 文章是转载 但是我在后面的案例加了不少注解并debug了 如有疑问 留言交流 其实我也不懂 原文链接 blog packagecloud io https zcfy cc article the definitive
  • 使用ASM编写 打印方法运行的时间 代码分析

    请先简单阅读下原文代码 https blog csdn net weixin 44618248 article details 107086410 可以对照源代码在阅读本文同时可以看得更清晰一些 注 以下属于个人学习 理解 如果偏颇过深 非
  • asm:常用语法

    常用语法 1 循环 1 1 使用条件跳转指令实现循环 1 2 使用LOOP指令实现循环 2 字符串 2 1 指定字符串的长度 2 2 字符串指令 2 3 重复前缀 3 数组 4 递归 5 宏 6 文件操作 7 内存管理 1 循环 1 1 使
  • asm:常见指令大全

    常见指令大全 算数指令 INC 指令 DEC 指令 ADD 指令 SUB指令 MUL指令 IMUL指令 DIV指令 IDIV指令 逻辑指令 AND指令 OR指令 XOR 指令 TEST指令 NOT指令 交换指令 xchg 比较指令 CMP指
  • 【asm基础】nasm和masm的一些区别

    差异点说明 1 nasm是区分大小写的 2 nasm中访问内存需要使用 将内存地址括起来 例如 bar equ 2 mov rax bar mov rax bar 这个才是存储地址中内容的操作 3 nasm不存储类型信息 所以也不能使用MO
  • 用汇编语言实现结构体的输入和保存

    COUNT EQU 1 ALL INPUT MACRO STRING NUM FUNCTION MOV DX OFFSET STRING MOV AH 9H INT 21H MOV DI OFFSET INFO NUM MOV AX SIZ

随机推荐