zorka源码解读之Instrument实现原理
主要用到三方面技术:
- beanshell来实现可扩展:告诉zorkaAgent插桩的具体需求,包括插桩的方法和值、插桩的时机、插桩追踪记录方式等。
- Instrument来通过代理的方式访问JVM,实现在类加载的时候访问类字节码。
- ASM字节码操纵框架,用于实现真正底层的类字节码的修改。
一、beanshell实现插桩具体需求(bsh如何将要插桩的内容告诉代理程序的?)
给classTransformer添加SpyDefinition的实例,SpyDefinition里面定义了各种插桩行为,这些行为传递到底层主要封装到SpyProbe和SpyProcessor中了。SpyProbe的实例集合和SpyProcessor的实例集合都是SpyDefinition的属性。


二、Instrument插桩过程
1、AgentMain.premain方法的执行
在JVM执行ClassLoader.defineClass之后,应用程序main方法执行之前,premain方法开始执行。
premain方法中主要执行两个任务:
1) AgentInstance.start()加载beanshell,给beanshell注册zorkaAgent中的lib,并执行bsh。bsh的执行,主要是往SpyClassTransformer(start的时候实例化transformer)中添加SpyDefinition。
SpyDefinition中包含了插桩的所有信息。
2)给instrumentation添加transformer。
2、classTransformer.transform方法的执行
每装载一个类,transformer的transform方法就会执行一次,看看是否需要转换。transform函数的最后,若返回null值,表示不需要进行类字节码的转化,否则返回转换后的class字节数组。
transform中核心的代码是调用ASM的字节码访问技术:
ClassReader cr = new ClassReader(cbf);//cbf是类字节码的字节数组
ClassWriter cw = new ClassWriter(cr, cbf[7] > (byte)0x32 ? ClassWriter.COMPUTE_FRAMES : 0);
ClassVisitor scv = createVisitor(classLoader, clazzName, found, tracer, cw);//found就是SpyDefinition的集合
cr.accept(scv, 0);//给classReader传递字节码访问者,这个方法里面开始正式的字节码访问。
buf = cw.toByteArray();
1)accept中开始visitor(SpyClassVisitor)的各种visit方法的调用。比如visit(访问类声明)、visitSource、visitOuterClass、visitInnerClass、readMethod(读取方法,让指定visitor访问)、readField、visitAnnotaiton、visitTypeAnnotation、visitAttribute、visitEnd,这些方法按一定顺序被执行。在这里我们关注readMethod的调用。
2)readMethod调用spyClassVisitor的visitMethod方法。visitMethod解析SpyDefinition,根据SpyMatcher匹配目标方法,获取SpyContext上下文传递给下一个节点访问者。比如方法访问者SpyMethodVisitor。这个对象会返回到readMethod方法中继续执行访问。
3)SpyMethodVisitor中的visit方法会被调用。其中有visitAnnotation、visitCode、visitInsn、visitMaxs等。
4)上面的visit访问会调用emitProbes方法。该访问会根据SpyContext中定义的SpyDefinition,SpyDefinition里面的probe进行插桩。
private int emitProbes(int stage, SpyContext ctx)
5)emitProbes方法遍历SpyContext里面的probe,调用probe.emit方法进行插桩。
zorka源码解读之Instrument实现原理的更多相关文章
- Vue源码--解读vue响应式原理
原文链接:https://geniuspeng.github.io/2018/01/05/vue-reactivity/ Vue的官方说明里有深入响应式原理这一节.在此官方也提到过: 当你把一个普通的 ...
- React 源码解读参考,理解原理。
Rubix - ReactJS Powered Admin Template 文档: http://rubix-docs.sketchpixy.com/ ===================== ...
- zorka源码解读之通过beanshell进行插桩的流程
zorka中插桩流程概述 1.在SpyDefinition中配置插桩属性,将SpyDefinition实例提交给插桩引擎.2.SpyDefinition实例中包含了插桩探针probes,probe插入 ...
- zorka源码解读之tracer内部实现
核心类: ZorkaAsyncThread.java protected BlockingQueue<T> submitQueue; /** * Processes single item ...
- zorka源码解读之Beanshell与zorka的交互实现
一.beanshell基础知识从应用程序中调用BeanShell创建一个BeanShell的解释器(interpreter)用eval()和source()命令可以对一个字符串求值和运行一个脚本文件使 ...
- Webpack探索【16】--- 懒加载构建原理详解(模块如何被组建&如何加载)&源码解读
本文主要说明Webpack懒加载构建和加载的原理,对构建后的源码进行分析. 一 说明 本文以一个简单的示例,通过对构建好的bundle.js源码进行分析,说明Webpack懒加载构建原理. 本文使用的 ...
- Webpack探索【15】--- 基础构建原理详解(模块如何被组建&如何加载)&源码解读
本文主要说明Webpack模块构建和加载的原理,对构建后的源码进行分析. 一 说明 本文以一个简单的示例,通过对构建好的bundle.js源码进行分析,说明Webpack的基础构建原理. 本文使用的W ...
- 2,MapReduce原理及源码解读
MapReduce原理及源码解读 目录 MapReduce原理及源码解读 一.分片 灵魂拷问:为什么要分片? 1.1 对谁分片 1.2 长度是否为0 1.3 是否可以分片 1.4 分片的大小 1.5 ...
- Vue 源码解读(3)—— 响应式原理
前言 上一篇文章 Vue 源码解读(2)-- Vue 初始化过程 详细讲解了 Vue 的初始化过程,明白了 new Vue(options) 都做了什么,其中关于 数据响应式 的实现用一句话简单的带过 ...
随机推荐
- ARM处理器解析
按图分析: ARM处理器有七种工作模式,为的是形成不同的使用级别,以防造成对系统的破坏.不同模式可以访问的寄存器不同,可以运行的指令不同. (1)user(10000):普通应用程序运行的模式(应用程 ...
- 如何同时打开两个excel
1. 打开一个excel1 2. 不要双击想要打开的excel2.右键excel应用的图标,选择excel2007. 3. 将excel2拖动到2所打开的新建excel中. 4. over.
- 小白搭建一个网站(DouPHP)
1)安装phpStudy_2014_setup.1413444920.exe 并启动数据库 2)将软件自带的WWW实例替换成我发的这个模板(DouPHP),网上也可以下载. 能找到更好模板的也可以不用 ...
- Spring系列之bean的使用
一.Bean的定义 <bean id="userDao" class="com.dev.spring.simple.MemoryUserDao"/> ...
- IoC/DI基本思想的演变
---------------------------------------------------------------------------------- (1)IoC/DI的概念 IoC ...
- NEERC2014 Eastern subregional
\ 先把furthur的超碉线段树粘过来 //#pragma comment(linker, "/STACK:102400000,102400000") #include<c ...
- 莫比乌斯环-vtkTriangleStrip
#ifndef INITIAL_OPENGL #define INITIAL_OPENGL #include <vtkAutoInit.h> VTK_MODULE_INIT(vtkRend ...
- nyoj 448 寻找最大数(贪心专题)
寻找最大数 时间限制:1000 ms | 内存限制:65535 KB 难度:2 描述 请在整数 n 中删除m个数字, 使得余下的数字按原次序组成的新数最大, 比如当n=920813467185 ...
- SSAS动态添加分区(一)
一.动态分区的好处就不说了,随着时间的推移,不可能一个度量值组都放在一个分区中,处理速度非常慢,如何动态添加分区,如何动态处理分区,成为了很多新手BI工程师一个头痛的问题,废话不多说,分享一下我的经验 ...
- Shell入门教程:Shell函数的返回值
shell函数返回值一般有3种方式: 1.return语句(默认的返回值) shell函数的返回值可以和其他语言的返回值一样,通过return语句返回. 比如: #!/bin/bash functio ...