主要用到三方面技术:

  1. beanshell来实现可扩展:告诉zorkaAgent插桩的具体需求,包括插桩的方法和值、插桩的时机、插桩追踪记录方式等。
  2. Instrument来通过代理的方式访问JVM,实现在类加载的时候访问类字节码。
  3. 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实现原理的更多相关文章

  1. Vue源码--解读vue响应式原理

    原文链接:https://geniuspeng.github.io/2018/01/05/vue-reactivity/ Vue的官方说明里有深入响应式原理这一节.在此官方也提到过: 当你把一个普通的 ...

  2. React 源码解读参考,理解原理。

    Rubix - ReactJS Powered Admin Template 文档:   http://rubix-docs.sketchpixy.com/ ===================== ...

  3. zorka源码解读之通过beanshell进行插桩的流程

    zorka中插桩流程概述 1.在SpyDefinition中配置插桩属性,将SpyDefinition实例提交给插桩引擎.2.SpyDefinition实例中包含了插桩探针probes,probe插入 ...

  4. zorka源码解读之tracer内部实现

    核心类: ZorkaAsyncThread.java protected BlockingQueue<T> submitQueue; /** * Processes single item ...

  5. zorka源码解读之Beanshell与zorka的交互实现

    一.beanshell基础知识从应用程序中调用BeanShell创建一个BeanShell的解释器(interpreter)用eval()和source()命令可以对一个字符串求值和运行一个脚本文件使 ...

  6. Webpack探索【16】--- 懒加载构建原理详解(模块如何被组建&如何加载)&源码解读

    本文主要说明Webpack懒加载构建和加载的原理,对构建后的源码进行分析. 一 说明 本文以一个简单的示例,通过对构建好的bundle.js源码进行分析,说明Webpack懒加载构建原理. 本文使用的 ...

  7. Webpack探索【15】--- 基础构建原理详解(模块如何被组建&如何加载)&源码解读

    本文主要说明Webpack模块构建和加载的原理,对构建后的源码进行分析. 一 说明 本文以一个简单的示例,通过对构建好的bundle.js源码进行分析,说明Webpack的基础构建原理. 本文使用的W ...

  8. 2,MapReduce原理及源码解读

    MapReduce原理及源码解读 目录 MapReduce原理及源码解读 一.分片 灵魂拷问:为什么要分片? 1.1 对谁分片 1.2 长度是否为0 1.3 是否可以分片 1.4 分片的大小 1.5 ...

  9. Vue 源码解读(3)—— 响应式原理

    前言 上一篇文章 Vue 源码解读(2)-- Vue 初始化过程 详细讲解了 Vue 的初始化过程,明白了 new Vue(options) 都做了什么,其中关于 数据响应式 的实现用一句话简单的带过 ...

随机推荐

  1. sql 从一个库中取某个表的数据导入到另一个库中相同结构的表中

    sql 2008 从一个库中把 某个表中的数据导入到另一个库中的具有相同结构的表中 use 库1 go insert into  库1.dbo.表1  select * from  库2.dbo.表1 ...

  2. cinnamon桌面安装在其他目录下

    cinnamon桌面还不错,不过默认只能安装在/usr目录下 有很多脚本中写死了是/usr目录 编译时如下模块需要打补丁: 1.cinnamon中,需要执行 sed -i 's|usr/share|u ...

  3. 从yield关键字看IEnumerable和Collection的区别

    C#的yield关键字由来以久,如果我没有记错的话,应该是在C# 2.0中被引入的.相信大家此关键字的用法已经了然于胸,很多人也了解yield背后的“延迟赋值”机制.但是即使你知道这个机制,你也很容易 ...

  4. ab 轻量的压测工具

    阅读:http://www.cnblogs.com/luminji/archive/2011/09/02/2163525.html

  5. Beanutils基本用法

    Beanutils用了魔术般的反射技术,实现了很多夸张有用的功能,都是C/C++时代不敢想的.无论谁的项目,始终一天都会用得上它.我算是后知后觉了,第一回看到它的时候居然错过. 1.属性的动态gett ...

  6. tyvj1938 最优战舰

    描述 太空战队顺利地完成了它的第一次使命,这一行动的受益者陆军本部当即决定,请陆军的战士们投票选出最优战舰并报司令总部进行表彰.为防止有人利用高科技手段造假,陆军本部决定使用最原始的方法进行投票.可不 ...

  7. 创建maven工程时总是带有后缀名Maven Webapp解决办法

    做项目时突然遇到了一个新问题,从前没有的,今天不知怎么了突然有了这个问题,maven创建web项目时多出了后缀名maven webapp ,很碍眼,而且访问路径还得删了,这个后缀名才可访问,所以找了答 ...

  8. PHP二维数组排序(list_order)

    /** * 对二维数组进行排序 * 模拟 数据表记录按字段排序 * * <code> * @list_order($list, $get['orderKey'], $get['orderT ...

  9. PHP之static静态变量详解(二)

    在看别人项目过程中,看到函数里面很多static修饰的变量,关于static修饰的变量,作用域,用法越看越困惑,所以查了下资料. static用法如下: 1.static 放在函数内部修饰变量 2.s ...

  10. (转)Intent flag 与启动模式的对应关系

    原文地址:http://www.cnblogs.com/ttylinux/p/4069513.html Activity有四种启动模式: 1.standard(标准)    2.singleTop   ...