从这篇博客开始,我会陆续介绍和总结一些自己认为Zorka源码中重要的部分,也帮助大家学习Java instrumentation之类的一些基本知识(其实对我自己来说也是个学习的过程)
可能大家最关心的,还是Zorka是怎样实现插桩(Instrumentation)的,所以这篇日志就简单讲讲这个,也顺便介绍一些阅读和学习开源项目的通用方法。
首先我们可以在这里:https://github.com/jitlogic/zorka下载其Master branch的压缩包,但是解压以后发现很复杂,这时候怎么快速入门呢,有一种方法:我们用压缩软件打开zorka.jar这个JAR包,然后查看META-INF下的MANIFEST.MF文件,可以看到中间有一行:Premain-Class: com.jitlogic.zorka.agent.AgentMain 这可以认为是Zorka的入口方法。我们将Zorka的源码导入Eclipse中(注意这个项目是基于Maven的,基于Maven的项目导入Eclipse,请参考我这篇日志)。然后打开上面这个类。可以看到这个类的一个方法是:public static void premain
(2015年9月10日更新:注意到之前写的将Zorka源码导入Eclipse的方法太复杂了,其实更简单的方法是:Import——Maven——Existing Maven Projects,然后定位到解压目录下就可以了。)
其注释写着:This is entry method of java agent. 所以就应该从这里看起了。关于这个方法为什么叫premain,具体原因有很多人解释过了,例如这里:http://blog.csdn.net/zhyhang/article/details/17027441 ,
我们可以看到,这个方法开始之后,Zorka Agent做了一些读取配置文件,生成instance的过程,具体细节这里就不介绍了,主要看看这部分代码:
if (instance.getConfig().boolCfg("spy", true)) {
addTransformer(instrumentation, instance.getClassTransformer(), retransformSupported);
MainSubmitter.setSubmitter(instance.getSubmitter());
MainSubmitter.setTracer(instance.getTracer());
}
简单来说,addTransformer这个方法用Reflection实现了插桩的目的,具体的细节大家可以查查其他的资料,我们需要关心的就是,这个instrumentation对象到底是什么东西?按照Zorka注释里的介绍,instrumentation reference to JVM instrumentation interface,instrumentation本身是一个接口:http://docs.oracle.com/javase/7/docs/api/java/lang/instrument/Instrumentation.html 说到这里,插一点题外话,实际上都可以通过Eclipse看到JDK的部分源码,具体的方法可以参考这里:http://blog.csdn.net/bruce128/article/details/6887732,这个接口中有一个方法叫:addTransformer 可以通过这个方法注册一个ClassFileTransformer,对于Zorka来讲,instance.getClassTransformer()这个方法就可以返回一个它自己实现的ClassFileTransformer的实例化类,我们具体看看这个方法:
public synchronized SpyClassTransformer getClassTransformer() {
if (classTransformer == null) {
classTransformer = new SpyClassTransformer(getSymbolRegistry(), getTracer(),
getConfig().boolCfg("zorka.spy.compute.frames", true), stats, getRetransformer());
}
return classTransformer;
}
很显然,接下来看看SpyClassTransformer这个类就知道怎么回事了。SpyClassTransformer implements ClassFileTransformer 可以看到,这个类确实实例化了ClassFileTransformer这个接口。这个接口中只定义了一个public byte[] transform方法,我们需要去实例化它。我们简单看看这个方法,基本上就搞清楚Zorka instrumentation的入口了。
简单说一下这个方法中的这两句:
ClassReader cr = new ClassReader(cbf);
ClassWriter cw = new ClassWriter(cr, doComputeFrames ? ClassWriter.COMPUTE_FRAMES : 0);
在这里就使用了ASM的一些功能。具体细节我就不介绍了。关于介绍的java.lang.instrument这个包的简单使用例子,感兴趣的朋友可以看看我很久之前写过的一篇博客: http://www.cnblogs.com/quyu/archive/2011/12/14/2287742.html ,还附带有一个简单的例子。