Closed linfan closed 2 years ago
非常专业的问题说明(包含复现代码工程) @linfan 👍 ❤️
想进一步挖一下,以更完整分析深入些解决这个问题。 原因如下:
2. 修复建议,在JavaAgent的Processor里直接忽略
java.util
包吧,这个包里本来也没有线程池
ClassCircularityError
的case来看,是在 java.util
包;
如果没有进一步确定原因,忽略 java.util
包后,其它包可能接着会再次成为问题项。TTL Agent
的扩展机制正在开发中,以允许业务写扩展;扩展Agent
功能 不期望有包被(Hard-Code)忽略/跳过。@linfan 有空方便一起分析原因以进一步解决吗? 😃
window10环境,jvm版本
java version "1.8.0_101"
Java(TM) SE Runtime Environment (build 1.8.0_101-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.101-b13, mixed mode)
我在cmd中使用
java -Dfile.encoding=utf-8 \
-Xbootclasspath/a:C:/mvn_repository/com/alibaba/transmittable-thread-local/2.12.1 \
-javaagent:C:/mvn_repository/com/alibaba/transmittable-thread-local/2.12.1/transmittable-thread-local-2.12.1.jar \
-jar hello-1.0.0.jar
命令启动jar包也遇到了类似的循环依赖的问题;
变更transmittable-thread-local版本为2.10.2,便不会再命令行遇到这个错误; 在idea中配置2.12.1版本或者2.10.2的上述同样的vm options,也没有遇到循环依赖的错误。
2021-12-13 16:04:00.562 SEVERE [main] TtlTransformer: Fail to transform class java/util/LinkedHashMap$LinkedKeySet, cause: java.lang.ClassCircularityError: java/util/LinkedHashMap$LinkedKeySet
java.lang.ClassCircularityError: java/util/LinkedHashMap$LinkedKeySet
at java.util.LinkedHashMap.keySet(Unknown Source)
at java.io.ExpiringCache.cleanup(Unknown Source)
at java.io.ExpiringCache.get(Unknown Source)
at java.io.WinNTFileSystem.canonicalize(Unknown Source)
at java.io.File.getCanonicalPath(Unknown Source)
at java.io.FilePermission$1.run(Unknown Source)
at java.io.FilePermission$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.io.FilePermission.init(Unknown Source)
at java.io.FilePermission.<init>(Unknown Source)
at sun.net.www.protocol.file.FileURLConnection.getPermission(Unknown Source)
at sun.net.www.protocol.jar.JarFileFactory.getPermission(Unknown Source)
at sun.net.www.protocol.jar.JarFileFactory.getCachedJarFile(Unknown Source)
at sun.net.www.protocol.jar.JarFileFactory.get(Unknown Source)
at sun.net.www.protocol.jar.JarURLConnection.connect(Unknown Source)
at sun.net.www.protocol.jar.JarURLConnection.getInputStream(Unknown Source)
at java.net.URL.openStream(Unknown Source)
at java.lang.ClassLoader.getSystemResourceAsStream(Unknown Source)
at java.lang.Class.getResourceAsStream(Unknown Source)
at com.alibaba.ttl.threadpool.agent.internal.javassist.ClassClassPath.openClassfile(ClassClassPath.java:80)
at com.alibaba.ttl.threadpool.agent.internal.javassist.ClassPoolTail.openClassfile(ClassPoolTail.java:334)
at com.alibaba.ttl.threadpool.agent.internal.javassist.ClassPool.openClassfile(ClassPool.java:613)
at com.alibaba.ttl.threadpool.agent.internal.javassist.CtClassType.getClassFile3(CtClassType.java:204)
at com.alibaba.ttl.threadpool.agent.internal.javassist.CtClassType.getClassFile2(CtClassType.java:178)
at com.alibaba.ttl.threadpool.agent.internal.javassist.CtClassType.getSuperclass(CtClassType.java:813)
at com.alibaba.ttl.threadpool.agent.internal.javassist.CtClassType.subclassOf(CtClassType.java:804)
at com.alibaba.ttl.threadpool.agent.internal.transformlet.impl.TtlExecutorTransformlet.doTransform(TtlExecutorTransformlet.java:73)
at com.alibaba.ttl.threadpool.agent.TtlTransformer.transform(TtlTransformer.java:58)
at sun.instrument.TransformerManager.transform(Unknown Source)
at sun.instrument.InstrumentationImpl.transform(Unknown Source)
at java.util.LinkedHashMap.keySet(Unknown Source)
at java.io.ExpiringCache.cleanup(Unknown Source)
at java.io.ExpiringCache.put(Unknown Source)
at java.io.WinNTFileSystem.canonicalize(Unknown Source)
at java.io.File.getCanonicalPath(Unknown Source)
at sun.security.provider.PolicyFile.canonPath(Unknown Source)
at sun.security.provider.PolicyFile.canonicalizeCodebase(Unknown Source)
at sun.security.provider.PolicyFile.getCodeSource(Unknown Source)
at sun.security.provider.PolicyFile.addGrantEntry(Unknown Source)
at sun.security.provider.PolicyFile.init(Unknown Source)
at sun.security.provider.PolicyFile.access$400(Unknown Source)
at sun.security.provider.PolicyFile$3.run(Unknown Source)
at sun.security.provider.PolicyFile$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.security.provider.PolicyFile.initPolicyFile(Unknown Source)
at sun.security.provider.PolicyFile.initPolicyFile(Unknown Source)
at sun.security.provider.PolicyFile.init(Unknown Source)
at sun.security.provider.PolicyFile.<init>(Unknown Source)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at java.lang.Class.newInstance(Unknown Source)
at java.security.Policy.getPolicyNoCheck(Unknown Source)
at java.security.ProtectionDomain.implies(Unknown Source)
at java.security.AccessControlContext.checkPermission(Unknown Source)
at java.security.AccessController.checkPermission(Unknown Source)
at ch.qos.logback.core.util.Loader$1.run(Loader.java:48)
at ch.qos.logback.core.util.Loader$1.run(Loader.java:45)
at java.security.AccessController.doPrivileged(Native Method)
at ch.qos.logback.core.util.Loader.<clinit>(Loader.java:45)
at ch.qos.logback.classic.util.ContextInitializer.findURLOfDefaultConfigurationFile(ContextInitializer.java:119)
at ch.qos.logback.classic.util.ContextInitializer.autoConfig(ContextInitializer.java:148)
at org.slf4j.impl.StaticLoggerBinder.init(StaticLoggerBinder.java:84)
at org.slf4j.impl.StaticLoggerBinder.<clinit>(StaticLoggerBinder.java:55)
at org.slf4j.LoggerFactory.bind(LoggerFactory.java:150)
at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:124)
at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:412)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:357)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:383)
2021-12-13 16:04:00.580 SEVERE [main] TtlTransformer: Fail to transform class java/util/LinkedHashMap$LinkedKeyIterator, cause: java.lang.ClassCircularityError: java/util/LinkedHashMap$LinkedKeyIterator
java.lang.ClassCircularityError: java/util/LinkedHashMap$LinkedKeyIterator
at java.util.LinkedHashMap$LinkedKeySet.iterator(Unknown Source)
at java.io.ExpiringCache.cleanup(Unknown Source)
at java.io.ExpiringCache.get(Unknown Source)
at java.io.WinNTFileSystem.canonicalize(Unknown Source)
at java.io.File.getCanonicalPath(Unknown Source)
at java.io.FilePermission$1.run(Unknown Source)
at java.io.FilePermission$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.io.FilePermission.init(Unknown Source)
at java.io.FilePermission.<init>(Unknown Source)
at sun.net.www.protocol.file.FileURLConnection.getPermission(Unknown Source)
at sun.net.www.protocol.jar.JarFileFactory.getPermission(Unknown Source)
at sun.net.www.protocol.jar.JarFileFactory.getCachedJarFile(Unknown Source)
at sun.net.www.protocol.jar.JarFileFactory.get(Unknown Source)
at sun.net.www.protocol.jar.JarURLConnection.connect(Unknown Source)
at sun.net.www.protocol.jar.JarURLConnection.getInputStream(Unknown Source)
at java.net.URL.openStream(Unknown Source)
at java.lang.ClassLoader.getSystemResourceAsStream(Unknown Source)
at java.lang.Class.getResourceAsStream(Unknown Source)
at com.alibaba.ttl.threadpool.agent.internal.javassist.ClassClassPath.openClassfile(ClassClassPath.java:80)
at com.alibaba.ttl.threadpool.agent.internal.javassist.ClassPoolTail.openClassfile(ClassPoolTail.java:334)
at com.alibaba.ttl.threadpool.agent.internal.javassist.ClassPool.openClassfile(ClassPool.java:613)
at com.alibaba.ttl.threadpool.agent.internal.javassist.CtClassType.getClassFile3(CtClassType.java:204)
at com.alibaba.ttl.threadpool.agent.internal.javassist.CtClassType.getClassFile2(CtClassType.java:178)
at com.alibaba.ttl.threadpool.agent.internal.javassist.CtClassType.getSuperclass(CtClassType.java:813)
at com.alibaba.ttl.threadpool.agent.internal.javassist.CtClassType.subclassOf(CtClassType.java:804)
at com.alibaba.ttl.threadpool.agent.internal.transformlet.impl.TtlExecutorTransformlet.doTransform(TtlExecutorTransformlet.java:73)
at com.alibaba.ttl.threadpool.agent.TtlTransformer.transform(TtlTransformer.java:58)
at sun.instrument.TransformerManager.transform(Unknown Source)
at sun.instrument.InstrumentationImpl.transform(Unknown Source)
at java.util.LinkedHashMap$LinkedKeySet.iterator(Unknown Source)
at java.io.ExpiringCache.cleanup(Unknown Source)
at java.io.ExpiringCache.put(Unknown Source)
at java.io.WinNTFileSystem.canonicalize(Unknown Source)
at java.io.File.getCanonicalPath(Unknown Source)
at sun.security.provider.PolicyFile.canonPath(Unknown Source)
at sun.security.provider.PolicyFile.canonicalizeCodebase(Unknown Source)
at sun.security.provider.PolicyFile.getCodeSource(Unknown Source)
at sun.security.provider.PolicyFile.addGrantEntry(Unknown Source)
at sun.security.provider.PolicyFile.init(Unknown Source)
at sun.security.provider.PolicyFile.access$400(Unknown Source)
at sun.security.provider.PolicyFile$3.run(Unknown Source)
at sun.security.provider.PolicyFile$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.security.provider.PolicyFile.initPolicyFile(Unknown Source)
at sun.security.provider.PolicyFile.initPolicyFile(Unknown Source)
at sun.security.provider.PolicyFile.init(Unknown Source)
at sun.security.provider.PolicyFile.<init>(Unknown Source)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at java.lang.Class.newInstance(Unknown Source)
at java.security.Policy.getPolicyNoCheck(Unknown Source)
at java.security.ProtectionDomain.implies(Unknown Source)
at java.security.AccessControlContext.checkPermission(Unknown Source)
at java.security.AccessController.checkPermission(Unknown Source)
at ch.qos.logback.core.util.Loader$1.run(Loader.java:48)
at ch.qos.logback.core.util.Loader$1.run(Loader.java:45)
at java.security.AccessController.doPrivileged(Native Method)
at ch.qos.logback.core.util.Loader.<clinit>(Loader.java:45)
at ch.qos.logback.classic.util.ContextInitializer.findURLOfDefaultConfigurationFile(ContextInitializer.java:119)
at ch.qos.logback.classic.util.ContextInitializer.autoConfig(ContextInitializer.java:148)
at org.slf4j.impl.StaticLoggerBinder.init(StaticLoggerBinder.java:84)
at org.slf4j.impl.StaticLoggerBinder.<clinit>(StaticLoggerBinder.java:55)
at org.slf4j.LoggerFactory.bind(LoggerFactory.java:150)
at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:124)
at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:412)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:357)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:383)
@linfan @xyc0123456789 发布了v2.12.3
https://github.com/alibaba/transmittable-thread-local/releases/tag/v2.12.3
包含这个问题的修复;可以试试是不是解决问题了? ❤️
PS: https://github.com/linfan/transmittable-thread-local-issue-278
在我MAC
开发机Java 8 (1.8.0_312)
上N次运行,没复现出来 😅
可能和 操作系统WINDOWS
或 Java
的小版本有关系。
# My java version
$ java -version
openjdk version "1.8.0_312"
OpenJDK Runtime Environment Corretto-8.312.07.1 (build 1.8.0_312-b07)
OpenJDK 64-Bit Server VM Corretto-8.312.07.1 (build 25.312-b07, mixed mode)
刚刚验证了一下,2.12.3
没有再出现前面的循环依赖的问题了。
我注意到在之前的环境下,cmd中使用
java -Dfile.encoding=utf-8
-Xbootclasspath/a:C:/mvn_repository/com/alibaba/transmittable-thread-local/2.12.1
-javaagent:C:/mvn_repository/com/alibaba/transmittable-thread-local/2.12.1/transmittable-thread-local-2.12.1.jar
-jar mdc-ttl-server-1.0-SNAPSHOT.jar
命令启动会出现循环依赖,而
java -Dfile.encoding=utf-8
-javaagent:C:/mvn_repository/com/alibaba/transmittable-thread-local/2.12.1/transmittable-thread-local-2.12.1.jar
-jar mdc-ttl-server-1.0-SNAPSHOT.jar
去掉了-Xbootclasspath
选项就不会出现循环依赖的错误
@xyc0123456789 谢谢你的验证。👍
去掉了
-Xbootclasspath
选项就不会出现循环依赖的错误
TTL
从v2.6.0
开始,加载TTL Agent
时会自动设置TTL Jar
到boot class path
上;
可以不需要为TTL
添加-Xbootclasspath JVM
参数。 @xyc0123456789
注意:不能修改从Maven
库下载的TTL Jar
文件名(形如transmittable-thread-local-2.x.y.jar
)。
如果修改了,则需要自己手动通过-Xbootclasspath JVM
参数来显式配置(就像TTL
之前的版本的做法一样)。
更多参见文档
@oldratlee 问题修复了,出现问题的根本原因可以分享说明下吗?
与 #234 应该是同一个问题,
2.12.1
版本在Mac下可复现。复现代码
https://github.com/linfan/transmittable-thread-local-issue-278
JVM版本
复现步骤
直接在代码根目录执行
./gradlew clean build --info
,即有一定概览会出现。可反复执行多次,一般三次以内至少会出现一次
ClassCircularityError
异常。报错的堆栈会有两种情况,其中第二种情况出现的概率比较高。第一种情况,报
LinkedHashMap.java:533
的位置:第二种情况,报
LinkedHashMap.java:543
的位置:其他信息
java.util
包吧,这个包里本来也没有线程池PS: 这个问题不影响使用,只是运行测试的时候会打印个异常,然后实际结果一切正常;不紧急。