2025-06-13
工具运维
0

目录

动态追踪技术底层分析
Java Agent 技术
premain
演示案例
agentmain
演示案例
借助Btrace手写动态追踪框架
BTrace是什么
BTrace与Arthas的关系
BTrace配置
实战案例
前置准备
监控DemoController的test方法,打印class和method以及方法的参数
监控DemoController的test方法,打印这个方法中所有的方法调用后的实例、参数、方法名、耗时(纳秒)
监控DemoController的exception方法,进行对应的处理
Btrace语法简介
BTrace注解
参数注解
方法注解
Btrace的限制
总结

对于 SkyWalkingZipkinArthas 来说都是无侵入式的组件,你是否有思考过其底层是如何实现?今天让我们了解下 动态追踪技术的底层分析

动态追踪技术底层分析

动态追踪技术是一个可以不用重启线上java项目来进行问题排查的技术,比如前面讲的 Arthas 就属于一种动态追踪的工具。Arthas里面提供的monitor还有watch等命令就是动态的追踪技术。

当然我们学技术要知其然还要知其所以然,Arthas工具的基础,就是 Java Agent 技术,可以利用它来构建一个附加的代理程序,用来协助检测性能,还可以替换一些现有功能,甚至 JDK 的一些类我们也能修改,有点像 JVM 级别的 AOP 功能。

Java Agent 技术

既然作为JVM的AOP,就必须要有AOP的功能,所以Java Agent提供了两个类似于AOP的方法:

  • 一个方法叫做premain方法,可以在main 运行之前的进行一些操作(Java 入口是一个 main 方法)
  • 一个是agentmain方法,是控制类运行时的行为(Arthas使用的就是这种)

但在一个JVM 中,只会调用一个

premain

演示案例

javaagent-demo

image.png

image.png

打包生成agent包,然后放入英文目录下

image.png

运行另外 一个项目,然后在VM参数加入jar的配置。

image.png

看到修改后的效果。

image.png

agentmain

具体javaagent-demo

这种模式一般用在一些诊断工具上(arthas之类的)。使用jdk/lib/tools.jar 中的工具类中的Attach API,可以动态的为运行中的程序加入一些功能。它的主要运行步骤如下:

  • 获取机器上运行的所有JVM 进程 ID;
  • 选择要诊断的jvm;
  • 将jvm 使用 attach 函数链接上;
  • 使用loadAgent 函数加载 agent,动态修改字节码;
  • 卸载jvm。

演示案例

Attach API 不是 Java 的标准 API,而是 Sun 公司提供的一套扩展 API,用来向目标 JVM ”附着”(Attach)代理工具程序的。有了它,开发者可以方便的监控一个 JVM,运行一个外加的代理程序。Attach API只有 2 个主要的类,都在 com.sun.tools.attach 包(在jdk的lib目录下tools.jar里面)里面:

VirtualMachine 代表一个 Java 虚拟机,也就是程序需要监控的目标虚拟机,提供了 JVM 枚举,Attach 动作和 Detach 动作(Attach 动作的相反行为,从 JVM 上面解除一个代理)等等 ;

VirtualMachineDescriptor 则是一个描述虚拟机的容器类,配合 VirtualMachine 类完成各种功能。

Java Attach API是一个API接口,JDK提供的,它可以将应用程序连接到另一个目标虚拟机。然后,您的应用程序可以将代理应用程序装入目标虚拟机,例如,用于执行监视状态之类的任务。

JVM Attach API功能上非常简单,主要功能如下

  • Attach到其中一个JVM上,建立通信管道
  • 让目标JVM加载Agent

image.png

下面的代码的主要功能是:

  1. 列出当前所有正在运行的 JVM 实例。
  2. 查找显示名称以 "MainRun" 结尾的 JVM 实例。
  3. 连接到该 JVM 实例并获取其 Java 版本信息。
  4. 打印出该版本信息,然后断开连接。

image.png

image.png

image.png

借助Btrace手写动态追踪框架

BTrace是什么

BTrace是基于Java语言的一个安全的、可提供动态追踪服务的工具。

BTrace基于ASM、Java Attach API、Instrument开发,为用户提供了很多注解。依靠这些注解,我们可以编写BTrace脚本(简单的Java代码)达到我们想要的效果,而不必深陷于ASM对字节码的操作中不可自拔。

BTrace和Arthas都是用于Java应用程序的动态监控和调试工具,但它们的设计目标和实现方式有所不同:

BTrace与Arthas的关系

  • 互补性:BTrace和Arthas可以视为互补的工具。BTrace适合于需要在特定场景下插桩追踪的情况,而Arthas则适合于实时监控和快速诊断。
  • 使用场景:在需要进行深入的性能分析或特定方法的追踪时,可以使用BTrace。而在需要快速定位问题或进行实时监控时,Arthas则是更好的选择。
  • 技术基础:两者都基于Java的动态代理和字节码操作,但实现细节和使用方式不同。

总之,BTrace和Arthas都是强大的Java工具,开发者可以根据具体需求选择使用其中一个或两个工具来帮助调试和监控Java应用程序。

BTrace配置

首先要下载btrace的压缩包,并解压,

image.png

配置环境变量

path变量新增

image.png

image.png

打开CMD命令行,输入btrace出现帮助及配置成功

image.png

实战案例

前置准备

1、准备一个springboot的工程,写一个controller。

image.png

2、写几个动态追踪框架的类(一般是单独的项目,这里简化放一起)

项目中引入需要引入几个jar包的依赖

image.png

image.png

image.png

监控DemoController的test方法,打印class和method以及方法的参数

image.png

效果

image.png

image.png

监控DemoController的test方法,打印这个方法中所有的方法调用后的实例、参数、方法名、耗时(纳秒)

image.png

image.png

监控DemoController的exception方法,进行对应的处理

image.png

image.png

image.png

image.png

Btrace语法简介

详细语法见官方:https://github.com/btraceio/btrace/blob/master/docs/BTraceTutorial.md

下面是我总结的一些核心的

BTrace注解

BTrace注解可以分为:

  • 类注解 @BTrace

  • 方法注解如 @OnMethod

  • 参数注解如 @ProbeClassName

参数注解
  • @ProbeClassName 用于标记处理方法的参数,仅用户@OnMethod, 该参数的值就是被跟踪的类名称

  • @ProbeMethodName 用于表姐处理方法的参数,仅用户 @OnMethod,该参数值是被跟踪方法名称

  • @Self 当前截取方法的封闭实例参数

  • @Return 当前截取方法的的返回值, 只对 location=@Location(Kind.RETURN) 生效

  • @Duration 当前截取方法的执行时间

  • @TargetInstance 当前截取方法内部调用的实例

  • @TargetMethodOrField 当前截取方法内部被调用的方法名

方法注解

@OnMethod - 用于指定跟踪方法到目标类,目标方法和目标位置

@Kind注解

  • Kind.ENTRY-被trace方法参数

  • Kind.RETURN-被trace方法返回值

  • Kind.THROW -抛异常

  • Kind.ARRAY_SET, Kind.ARRAY_GET -数组索引

  • Kind.CATCH -捕获异常

  • Kind.FIELD_SET -属性值

  • Kind.LINE -行号

  • Kind.NEW -类名

  • Kind.ERROR -抛异常

@OnTimer - 用于指定跟踪操作定时执行。value用于指定时间间隔

@OnError - 当trace代码抛异常或者错误时,该注解的方法会被执行.如果同一个trace脚本中其他方法抛异常,该注解方法也会被执行。

Btrace的限制

BTrace最终借Instrument实现class的替换。出于安全考虑,Instrument在使用上存在诸多的限制,这就好比给一架正在飞行的飞机换发动机一样一样的,因此BTrace脚本的限制如下:

  1. 不允许创建对象
  2. 不允许创建数组
  3. 不允许抛异常
  4. 不允许catch异常

不允许随意调用其他对象或者类的方法,只允许调用com.sun.btrace.BTraceUtils中提供的静态方法(一些数据处理和信息输出工具)

  1. 不允许改变类的属性

  2. 不允许有成员变量和方法,只允许存在static public void方法

  3. 不允许有内部类、嵌套类

  4. 不允许有同步方法和同步块

  5. 不允许有循环

  6. 不允许随意继承其他类(当然,java.lang.Object除外)

  7. 不允许实现接口

  8. 不允许使用assert

  9. 不允许使用Class对象

如此多的限制,其实可以理解。BTrace要做的是,虽然修改了字节码,但是除了输出需要的信息外,对整个程序的正常运行并没有影响。

总结

其实作为Java的动态追踪技术,站在比较底层的角度上来说,底层无非就是基于ASM、Java Attach API、Instrument开发的创建。Arthas都是针前面这些技术的一个封装而已。

Btrace功能虽然强大,但都是比较难入门,这就是为什么 Btrace 出来这么多年,还是只在小范围内被使用。相对来说,Arthas 显的友好而且安全的多。

但无论工具如何强大,一些基础知识是需要牢固掌握的,否则,工具中出现的那些术语,也会让人一头雾水。

工具常变,但基础更加重要。如果你想要一个适应性更强的技术栈,还是要多花点时间在原始的排查方法上。

本文作者:柳始恭

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!