本文基于 SkyWalking-Java-agent 8.15.0 版本
SkyWalking 采用 ByteBuddy 进行字节码的修改
// 3.定制化Agent行为
// 创建 ByteBuddy 实例
final ByteBuddy byteBuddy = new ByteBuddy().with(TypeValidation.of(Config.Agent.IS_OPEN_DEBUGGING_CLASS));
// 指定 ByteBuddy 要忽略的类
AgentBuilder agentBuilder = new AgentBuilder.Default(byteBuddy).ignore(
nameStartsWith("net.bytebuddy.")
.or(nameStartsWith("org.slf4j."))
.or(nameStartsWith("org.groovy."))
.or(nameContains("javassist"))
.or(nameContains(".asm."))
.or(nameContains(".reflectasm."))
.or(nameStartsWith("sun.reflect"))
.or(allSkyWalkingAgentExcludeToolkit())
.or(ElementMatchers.isSynthetic()));
// 1)将必要的类注入到Bootstrap ClassLoader
JDK9ModuleExporter.EdgeClasses edgeClasses = new JDK9ModuleExporter.EdgeClasses();
try {
agentBuilder = BootstrapInstrumentBoost.inject(pluginFinder, instrumentation, agentBuilder, edgeClasses);
} catch (Exception e) {
LOGGER.error(e, "SkyWalking agent inject bootstrap instrumentation failure. Shutting down.");
return;
}
// 解决JDK模块系统的跨模块类访问
try {
agentBuilder = JDK9ModuleExporter.openReadEdge(instrumentation, agentBuilder, edgeClasses);
} catch (Exception e) {
LOGGER.error(e, "SkyWalking agent open read edge in JDK 9+ failure. Shutting down.");
return;
}
// 将修改后的字节码保存到磁盘/内存上
if (Config.Agent.IS_CACHE_ENHANCED_CLASS) {
try {
agentBuilder = agentBuilder.with(new CacheableTransformerDecorator(Config.Agent.CLASS_CACHE_MODE));
LOGGER.info("SkyWalking agent class cache [{}] activated.", Config.Agent.CLASS_CACHE_MODE);
} catch (Exception e) {
LOGGER.error(e, "SkyWalking agent can't active class cache.");
}
}
agentBuilder.type(pluginFinder.buildMatch()) // 指定ByteBuddy要拦截的类
.transform(new Transformer(pluginFinder))
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION) // redefine和retransform的区别在于是否保留修改前的内容
.with(new RedefinitionListener())
.with(new Listener())
.installOn(instrumentation);
1. 创建 ByteBuddy 实例
// 创建 ByteBuddy 实例
final ByteBuddy byteBuddy = new ByteBuddy().with(TypeValidation.of(Config.Agent.IS_OPEN_DEBUGGING_CLASS));
2. 指定 ByteBuddy 要忽略的类
// 指定 ByteBuddy 要忽略的类
AgentBuilder agentBuilder = new AgentBuilder.Default(byteBuddy).ignore(
nameStartsWith("net.bytebuddy.")
.or(nameStartsWith("org.slf4j."))
.or(nameStartsWith("org.groovy."))
.or(nameContains("javassist"))
.or(nameContains(".asm."))
.or(nameContains(".reflectasm."))
.or(nameStartsWith("sun.reflect"))
.or(allSkyWalkingAgentExcludeToolkit())
.or(ElementMatchers.isSynthetic()));
3. 将必要的类注入到 BootstrapClassLoader 中
// 1)将必要的类注入到Bootstrap ClassLoader
JDK9ModuleExporter.EdgeClasses edgeClasses = new JDK9ModuleExporter.EdgeClasses();
try {
agentBuilder = BootstrapInstrumentBoost.inject(pluginFinder, instrumentation, agentBuilder, edgeClasses);
} catch (Exception e) {
LOGGER.error(e, "SkyWalking agent inject bootstrap instrumentation failure. Shutting down.");
return;
}
4. 解决 JDK 模块系统的跨模块类访问
// 解决JDK模块系统的跨模块类访问
try {
agentBuilder = JDK9ModuleExporter.openReadEdge(instrumentation, agentBuilder, edgeClasses);
} catch (Exception e) {
LOGGER.error(e, "SkyWalking agent open read edge in JDK 9+ failure. Shutting down.");
return;
}
5. 根据配置决定是否将修改后的字节码保存到磁盘/内存上
// 将修改后的字节码保存到磁盘/内存上
if (Config.Agent.IS_CACHE_ENHANCED_CLASS) {
try {
agentBuilder = agentBuilder.with(new CacheableTransformerDecorator(Config.Agent.CLASS_CACHE_MODE));
LOGGER.info("SkyWalking agent class cache [{}] activated.", Config.Agent.CLASS_CACHE_MODE);
} catch (Exception e) {
LOGGER.error(e, "SkyWalking agent can't active class cache.");
}
}
6. 细节定制
agentBuilder.type(pluginFinder.buildMatch()) // 指定ByteBuddy要拦截的类
.transform(new Transformer(pluginFinder))
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION) // redefine和retransform的区别在于是否保留修改前的内容
.with(new RedefinitionListener()) // 注册监听器
.with(new Listener()) // 注册监听器
.installOn(instrumentation); // 将 Agent 安装到 Instrumentation