低版本skywalking与LinkAgent不兼容怎么办?记一次详细的解决过程

我们在github上收到社区用户的问题反馈:

用户原先应用已经接入skywalking,需要再接入数列的LinkAgent时启动会抛java.lang.UnsupportedOperationException,导致应用启动失败。

 也就是说在不修改代码的情况下如果需要启动应用,skywalking和LinkAgent只能存在一个,两者不能同时存在。skywalking与LinkAgent不兼容该如何解决?本文将围绕这个问题的详细展开。 skywalking是分布式系统的应用程序性能监视工具,大家相对熟悉,可有的人并不了解Agent,这里稍微科普一下:

agent是什么

介绍javaagent之前也要介绍另一个概念JVMTI。 JVMTI是JDK提供的一套用于开发JVM监控, 问题定位与性能调优工具的通用编程接口(API)。 通过JVM TI,我们可以开发各式各样的JVMTI Agent。这个Agent的表现形式是一个以C/C++语言编写的动态共享库。 javaagent可以帮助我们快速使用JVMTI的功能,又不需要重写编写C/C++的底层库。

javaagent是依赖java底层提供的一个叫instrument的JVMTI Agent。这个agent又叫JPLISAgent(Java Programming Language Instrumentation Services Agent)

简单来说,javaagent是一个JVM的“插件”。 在java运行命令中 javaagent是一个参数,用来指定agent。

agent能干什么

  • 可以在加载class文件之前进行拦截并把字节码做修改。
  • 可以在运行期对已加载类的字节码做变更,但是这种情况下会有很多的限制。
  • 还有其他一些小众的功能
    • 获取所有已经加载过的类
    • 获取所有已经初始化过的类(执行过 clinit 方法,是上面的一个子集)
    • 获取某个对象的大小
    • 将某个jar加入到bootstrap classpath里作为高优先级被bootstrapClassloader 加载
    • 将某个jar加入到classpath里供AppClassloard去加载
    • 设置某些native方法的前缀,主要在查找native方法的时候做规则匹配

总的来说可以让JVM按照我们的预期逻辑去执行。 最主要的也是使用最广的功能就是对字节码的修改。通过对字节码的修改我们就可以实现对JAVA底层源码的重写,也正好可以满足我之前的需求。 我们还可以做:

  • 完全非侵入式的进行代码埋点,进行系统监控
  • 修改JAVA底层源码,进行JVM自定义
  • 实现AOP动态代理

agent 的两种使用方式

  1. 在 JVM 启动的时候加载,通过 javaagent 启动参数 java -javaagent:myagent.jar MyMain,这种方式在程序 main 方法执行之前执行 agent 中的 premain 方法
public static void premain(String agentArgument, Instrumentation instrumentation) throws Exception
  1. 在 JVM 启动后 Attach,通过 Attach API 进行加载,这种方式会在 agent 加载以后执行 agentmain 方法
public static void agentmain(String agentArgument, Instrumentation instrumentation) throws Exception

这两个方法都有两个参数

第一个 agentArgument 是 agent 的启动参数,可以在 JVM 启动命令行中设置,比如java -javaagent:<jarfile>=appId:agent-demo,agentType:singleJar test.jar的情况下 agentArgument 的值为 “appId:agent-demo,agentType:singleJar”。

第二个 instrumentation 是 java.lang.instrument.Instrumentation 的实例,可以通过 addTransformer 方法设置一个 ClassFileTransformer。

第一步:问题分析

异常信息是说在重新定义某个类的时候,原先的父类或者接口类发生了改变,导致重新定义失败。可是在没有使用skywalking的时候,数列LinkAgent与其他的一些agent并没有出现过类似的兼容性问题。 在github上搜索发现发现有人提过skywalking和arthas的兼容性问题。链接🔗

 问题原因skywalking官方也给出了答复: 当 Java 应用程序启动时,SkyWalking 代理使用 ByteBuddy 转换类。 ByteBuddy 每次都会生成具有不同随机名称的辅助类。 当另一个 Java 代理重新转换同一个类时,它会触发 SkyWalking 代理再次增强该类。 由于 ByteBuddy 重新生成了字节码,修改了字段和导入的类名,JVM 对类字节码的验证失败,因此重新转换类将不成功。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值