本文基于 SkyWalking-Java-agent 8.15.0 版本
Java agent
两种方式
静态启动
以命令参数的方式启动:
-javaagent: jarpath[ =options]
- jarpath:agent JAR 文件的绝对路径
- options:agent可选项
public static void
premain(String agentArgs, Instrumentation inst);
如果agent没有实现该方法的话,JVM会采用尝试访问以下方法:
public static void
premain(String agentArgs);
动态附加
JVM 启动后再启动 agent
public static void
agentmain(String agentArgs, Instrumentation inst);
如果agent没有实现该方法的话,JVM会采用尝试访问以下方法:
public static void
agentmain(String agentArgs);
参考:docs.oracle.com/javase/8/do…
SkyWalking agent
采用 静态启动 的方式,将 Java agent 嵌入到 Java 应用里面,通过代理 JVM 上运行的服务,修改字节码实现信息的获取。SkyWalking agent 的入口是 org.apache.skywalking.apm.agent.SkyWalkingAgent
启动流程
初始化配置
try {
// 1.初始化配置
SnifferConfigInitializer.initializeCoreConfig(agentArgs);
} catch (Exception e) {
// try to resolve a new logger, and use the new logger to write the error log here
LogManager.getLogger(SkyWalkingAgent.class)
.error(e, "SkyWalking agent initialized failure. Shutting down.");
return;
} finally {
// refresh logger again after initialization finishes
LOGGER = LogManager.getLogger(SkyWalkingAgent.class);
}
agentArgs:agent的参数。启动agent时,会通过 -javaagent的方式,比如:
- -javaagent:/path/to/agent.jar=agentArgs
- -javaagent:/path/to/agent.jar=k1=v1,k2=v2...
第一个=后面的均为 agentArgs 的参数。agentArgs 使用=将键值拼凑到 jarpath 的后面
-javaagent参数必须在-jar之前
加载插件
try {
// 2.加载插件
pluginFinder = new PluginFinder(new PluginBootstrap().loadPlugins());
} catch (AgentPackageNotFoundException ape) {
LOGGER.error(ape, "Locate agent.jar failure. Shutting down.");
return;
} catch (Exception e) {
LOGGER.error(e, "SkyWalking agent initialized failure. Shutting down.");
return;
}
定制化 Agent 行为
// 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())
.transform(new Transformer(pluginFinder))
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.with(new RedefinitionListener())
.with(new Listener())
.installOn(instrumentation);
加载服务
try {
// 4.启动服务
ServiceManager.INSTANCE.boot();
} catch (Exception e) {
LOGGER.error(e, "Skywalking agent boot failure.");
}
注册关闭钩子
// 5.注册关闭钩子
Runtime.getRuntime()
.addShutdownHook(new Thread(ServiceManager.INSTANCE::shutdown, "skywalking service shutdown thread"));