一、maven打包agent,install之后的zip解压,被检测项目的tomcat环境变量Arguments中加入代码-javaagent:D:\APM\pinpoint-agent-1.6.0\pinpoint-bootstrap-1.6.0.jar -Dpinpoint.agentId=test_web_local -Dpinpoint.applicationName=test_web_local 。
二、被检测tomcat启动时长设置延长100倍后,启动web项目,断点设置在PinpointBootStrap.java文件的premain方法中。
三、打开D:\APM\pinpoint-agent-1.6.0\log文件夹,发现test_web_local-pinpoint.log日志文件生成。
四、LoadState启动状态实例生成,LoadState对的属性对象AtomicBoolean设置初始值,启动时利用魔法类Unsafe的CAS来实现线程安全(CAS比较并替换,魔法类Unsafe不被GC回收需要手动free。详见Java魔法类:sun.misc.Unsafe - 素轩 - 博客园)。
五、参数比配到Map,argsToMap;
六、实例化agent目录类路径解析器,并启动认证方法:
- 首先查找agent所需的jar是否存在,我的路径参数是C:\tomcat\eclipse-luna-tomcat-7.0.47\bin\bootstrap.jar;C:\tomcat\eclipse-luna-tomcat-7.0.47\bin\tomcat-juli.jar;C:\Program Files\Java\jdk1.7.0_80\lib\tools.jar;D:\APM\pinpoint-agent-1.6.0\pinpoint-bootstrap-1.6.0.jar;
- 利用正则表达式,把可以使用的pinpoint-bootstrap-1.6.0.jar和其路径解析出来;
- 记录到log文件;
- 需要加载的jar有:pinpoint-commons-1.6.0.jar、pinpoint-commons-1.6.0.jar、pinpoint-bootstrap-core-optional-1.6.0.jar、httpclient-4.3.jar、httpcore-4.3.jar和commons-logging-1.2.jar。
----------------------------------------------------------------------------------------------------------------------
七、进入ClassPathResolver.verify():针对不同的jar输入不同的路径参数,调用get***JarFile方法获取到jar实例,并添加到bootstrap启动对象中去。顺序为:agentJarNotFound (首先要用findAgentJar()方法确认所有的jar是否存在,其中还使用了findFromBootDir方法,利用正则表达式去获取jar的文件路径) → pinpointCommonsJar → bootStrapCoreJarFile → bootStrapCoreOptionalJar → httpclientJarFile → httpcoreJarFile → commonsLoggingJarFile,开始bootstrapJarFile的装载工作(调用appendToBootstrapClassLoader)。
八、在获取jar路径的时候,根据需要,调用toCanonicalPath或getAbsolutePath(看不出区别其实,可能前者会根据系统规范去做变换)。
九、装载jar包到增强器Instrumentation:获取jar队列List,循环调用appendToBootstrapClassLoaderSearch。
十、调用PinpointStarter.start():
- 获取HashTable形式的Properties配置文件;
- IdValidator有一个比较有意思的调用,同名无参方法调用了有参方法,然后赋值确认获取的property到自身属性;
- 在getValidId中方法中,记录信息到日志;
- 调用了一个工具类IdValidateUtils,在日志信息中记录了value的length,不明白是为什么;
- 设置了MAX_ID_LENGTH=24,为最大id长度,原因未知。
- 引入config,调用了ProductInfo的final String NAME = "pinpoint",不清楚为什么要单独写在一个类文件中,是怕被恶意修改吗?
- 被读取的配置文件应该就是pinpoint.config,但是pinpointConfigFormSystemProperty为null,是路径不全的问题导致的吗?
- classPathAgentConfigPath获取的路径是完整的D:\APM\pinpoint-agent-1.6.0\pinpoint.config,返回到start()方法的configPath。
- DefaultProfilerConfig配置属性获取112行(第十一点详谈)。
- 调用saveLogFilePath,设置log文件位置D:\APM\pinpoint-agent-1.6.0\log。
- 调用savePinpointVersion,设置版本号为strace_1.6.0-1.0-1。
十一、问题:1、pinpoint.config的属性都配置到什么地方去了?
十二、调用DefaultAgent方法:1、在bindPLoggerFactory中绑定日志Slf4jLoggerBinder,由PLoggerFactory去初始化;2、绑定interceptorRegistryBinder注册拦截器;3、获取serviceTypeRegistryService服务类型注册服务实例;4、调用dumpSystemProperties()方法,获取java运行环境变量、jdk信息、jdk生产商信息,并记录到日志文件。
-----------------------------------------------------------------------------------------------
十三、增强器引擎:在pinpoint-profiler中的DefaultAgent.java中,调用createInstrumentEngine方法,根据pinpoint.config中配置的engine,选择调用的引擎是ASM还是JavaAssist。
十四、加载插件:在pinpoint-profiler中的DefaultAgent.java中,调用pluginContexts = loadPlugins(agentOption),ProfilerPluginLoader中的pluginJars中,保存了所有jar包形式的插件的完整物理路径。
十五、加载转换器:在pinpoint-profiler中的ClassFileTransformerDispatcher.java,调用createTransformerRegistry进行转换器的创建和注册。创建转换器:实例化DefaultTransformerRegistry。添加转换器:调用在pinpoint-profiler中的DefaultTransformerRegistry.java的addTransformer方法。
十六、字节码转换:在pinpoint-profiler中的DefaultAgent.java,调用wrapClassFileTransformer,ASMBytecodeDumpService声明转换器,即BytecodeDumpTransformer的transform方法。instrumentation中加入转换器wrappedTransformer。