ForAdvice#include引入类在平台/启动类加载器场景的可用性咨询
解决方案
- 方案1:将自定义依赖类加入启动类加载器路径
打包Agent jar时,在manifest配置文件中添加Boot-Class-Path属性,指定存放SocketLifespanKeeper、NioSocketConnectAdvice这些自定义类的jar路径。启动类加载器是所有类加载器的父加载器,平台类加载器加载的类可以直接访问到启动类路径下的自定义类。
Maven打包参考配置:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <archive> <manifestEntries> <Premain-Class>你的Agent全限定名</Premain-Class> <Boot-Class-Path>你的agent jar名称.jar</Boot-Class-Path> <Can-Redefine-Classes>true</Can-Redefine-Classes> <Can-Retransform-Classes>true</Can-Retransform-Classes> </manifestEntries> </archive> </configuration> </plugin>
- 方案2:将自定义类注入到平台类加载器
利用ByteBuddy的ClassInjector能力,在注册Transformer之前,把需要用到的自定义类注入到平台类加载器中:
// 注入自定义生命周期管理类到平台类加载器 ClassFileLocator locator = ClassFileLocator.ForClassLoader.of(SocketAgent.class.getClassLoader()); TypeDescription keeperType = TypePool.Default.ofSystemLoader() .describe("pbouda.agents.socket.advice.SocketLifespanKeeper") .resolve(); ClassInjector.UsingUnsafe.ofPlatformLoader() .inject(Collections.singletonMap(keeperType, locator.locate(keeperType.getName()).resolve()));
- 方案3:规避自定义类依赖
如果只是需要在connect和close方法之间传递时间戳,也可以直接把存储逻辑(比如静态WeakHashMap,key为NioSocketImpl实例,value为时间戳)直接写在Advice类中,避免引入额外的自定义类依赖,从根源解决类找不到问题。
注意事项
- 如果选择注入类到平台类加载器,要先判断类是否已经被加载,避免重复注入抛出异常
- 放到启动类路径的自定义类不要引入其他不在启动类路径中的第三方依赖,否则仍然会触发类找不到错误
内容的提问来源于stack exchange,提问作者Petr Bouda
相关产品推荐
相关产品推荐

