启动方式
静态启动: 使用 -javaagent 参数
入口方法 premain()
在类加载时可以对字节码做任意修改,只要最后的结果符合字节码规范
SkyWalking 只支持这种方式启动 Agent
典型应用:APM 监控
动态附加:使用 Attach API
入口方法 agentmain()
类已经完成加载并使用,这时候只能对目标类的字节码做有限修改
不能增减父类
不能增加接口
不能更改 field
典型应用:系统诊断 Arthas,JVM-SANDBOX
启动流程
<div>SnifferConfigInitializer.initialize()<br>初始化配置<br></div>
<div>SnifferConfigInitializer.loadConfig()<br></div>读取配置文件 /config/agent.config
<div>ConfigInitializer.initialize()<br></div>将上面读取到的配置属性赋值给 Config.Class
<div>SnifferConfigInitializer.overrideConfigBySystemProp()<br></div>使用系统环境变量覆盖, 环境变量必须以 skywalking 开头<br>
<div>SnifferConfigInitializer.overrideConfigByAgentOptions()<br></div>使用 agent 参数覆盖,优先级最高
优先级从低到高
<div></div><div>new PluginFinder(new PluginBootstrap().loadPlugins())<br>加载插件并分类</div>
<div>PluginBootstrap.loadPlugins()<br></div>加载所有插件
AgentClassLoader.initDefaultLoader()<div></div><div>初始化 AgentClassLoader</div>
PluginResourcesResolver.getResources()<div></div><div>读取所有的 skywalking-plugin.def 资源文件</div>
PluginCfg.load()<div></div><div>解析文件内容, 将其封装成 PluginDefine 集合</div>
AbstractClassEnhancePluginDefine<div></div><div>使用 classloader 实例化插件对象</div>
<div>new PluginFinder()<br>在构造方法中对所有插件进行分类</div>
定制 Agent
创建 ByteBuddy 实例
指定需要忽略增强的类
BootstrapInstrumentBoost.inject()<br>把一些必要的工具类注册到 Bootstrap ClassLoader 中
BootstrapInstrumentBoost.prepareJREInstrumentation()<br>把 jdk 核心类库的动态生成的代理模板放到 classesTypeMap 中
把 skywalking 的一些核心工具类加载到 classesTypeMap
把 ByteBuddy 的一些核心工具类加载到 classesTypeMap
把 classesTypeMap 中定义的一些字节码加载到 BootstrapCL 中
定制 agentBuilder
type(pluginFinder.buildMatch())<br>指定要拦截的类, 这里构造一个巨大的插件查询条件
transform(new Transformer(pluginFinder))<br>指定 Transformer 插桩增强类<br>
with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)<br>指定字节码增强的模式,使用 RETRANSFORMATION<br>
with(new Listener())<br>对 Transformer 后的监听, 输出日志<br>
installOn(instrumentation)<br>将 Agent 安装到 instrumentation
ServiceManager.INSTANCE.boot()<br>加载并启动服务
ServiceManager.loadAllServices()<br>加载所有服务实例,需要实现 BootService 接口
ServiceManager.load()<br>使用 serviceloader 加载所有的 BootService SPI 实例<br>
@DefaultImplementor<br>默认实现
@OverrideImplementor<br>覆盖实现
ServiceManager.prepare()<br>分别调用 prepare() 方法<br>
ServiceManager.startup()<br>分别调用 startup() 方法<br>
ServiceManager.onComplete()<br>分别调用 onComplete() 方法<br>
注册 JVM ShutdownHook
ServiceManager.shutdown()<br>分别调用 shutdown() 方法