-
Notifications
You must be signed in to change notification settings - Fork 26.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Dubbo-2.7.10] Fix setSkyWalkingDynamicField(java.lang.Object) not found
#7517
Conversation
setSkyWalkingDynamicField(java.lang.Object) not found
setSkyWalkingDynamicField(java.lang.Object) not found
Dubbo+SkyWalking使用导致应用启动失败1.现象:在10357启动启动失败,并包含部分和SkyWalking相关的日志,使用了SkyWalking可选插件包spring-annotation-plugin
2.原因排查 排查该问题我们需要先明确几点: 2.1 SkyWalking在增强某个类的成员方法时(非静态方法),会为修改该类字节码,会为其增加_$EnhancedClassField_ws字段,见代码1,并使其实现org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance接口,该接口中存在两个方法,见代码2。
2.2 当某个类被SkyWalking增强后,可以通过反射机制查看到SkyWalking为其增加的getSkyWalkingDynamicField(),setSkyWalkingDynamicField这两个方法。还有就有就是如果没有使用javaagent相关机制,没有办法获取到jvm中被其他agent增强后的字节码,简单来说没有特殊机制没有办法获取到被增强后的字节码(或许有,我还不知道相关的办法)。 有了上述两点支撑,对于接下来排查问题就比较方便了。 2.3 问题发生的原因,我们可以看到在异常中存在setSkyWalkingDynamicField(java.lang.Object) not found in com.zhangmen.lesson.service.LessonSynInfoServiceImpl这个信息,当我看到这个信息的时候,我有两个怀疑点,1. 为什么dubbo的代码代理了setSkyWalkingDynamicField(java.lang.Object) 这个方法,2. com.zhangmen.lesson.service.LessonSynInfoServiceImpl这个类在加载完成后,里面肯定是存在setSkyWalkingDynamicField(java.lang.Object) 这个方法,为什么dubbo字节码代理的时候却说没有找到该方法。接下来我看了一下dubbo(2.8.4-SNAPSHOT)生成代理的代码如下,为了方便分析问题,添加了部分注释。
2.4 dubbo自身使用javassist来生成相关的动态类,用来代理真实的方法,我们定位到异常栈发生异常的方法,接下来我们主要关注targetClass从那里获取的,并且为什么没有setSkyWalkingDynamicField(java.lang.Object) 这个方法。
lookupMethod相关逻辑如下,可以看到是通过解析classFile来实现的:
于是我们把定位targetClass,转换为了classfile从何而来,最终定位到targetClass来源于javassist.ClassPool#createCtClass,,在创建CtClass时调用了如下构造函数,但是这里面的classfile并没有被赋值,但是在该类的父类中存在getClassFile方法,并在该方法中返回this.getClassFile2(),通过getClassFile2()相关的逻辑我们知道了classfile最终来源于读取了classpath下的类源码文件,而在该源码中肯定是不存在和SkyWalking相关的代码。
问题解决: Dubbo这种在代理时通过反射获取方法然后在生成类时的逻辑有些问题,在反射时获取的方法有可能是增强后的,有可能多添加方法,但是在生成类时却获取了原字节码文件中的方法,导致javassist生成类时字节码校验失败。 修复办法: 1.修改dubbo源码com.alibaba.dubbo.common.bytecode.Wrapper#makeWrapper逻辑,在通过javassist获取源文件中的方法,和最终的生成、校验逻辑一致。 2.其他办法暂时还没有... |
Codecov Report
@@ Coverage Diff @@
## master #7517 +/- ##
============================================
- Coverage 59.24% 58.86% -0.39%
+ Complexity 503 500 -3
============================================
Files 1079 1079
Lines 43385 43350 -35
Branches 6329 6297 -32
============================================
- Hits 25704 25516 -188
- Misses 14842 14989 +147
- Partials 2839 2845 +6 Continue to review full report at Codecov.
|
…ound` (apache#7517) * Fix `setSkyWalkingDynamicField(java.lang.Object) not found` * Polishing. * Polishing. * Polishing.
What is the purpose of the change
Brief changelog
Verifying this change
[Dubbo-XXX] Fix UnknownException when host config not exist #XXX
. Each commit in the pull request should have a meaningful subject line and body.mvn clean install -DskipTests=false
&mvn clean test-compile failsafe:integration-test
to make sure unit-test and integration-test pass.Fix
setSkyWalkingDynamicField(java.lang.Object) not found
,the comment is a detailed description, in order to avoid misunderstanding, sorry to use Chinese ,link issue, #2830