主要用到三方面技术:

  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. 最简单的STM32入门教程----闪烁LED

    本文讲述的是如何从零开始,使用keil建立一个简单的STM32的工程,并闪烁LED灯,给小白看. 第零步,当然首先你得有一个STM32的板子,其IO口上接了一个LED... 第一步,建立一个文件夹0. ...

  2. Sql Server FOR XML PATH

    FOR XML PATH 有的人可能知道有的人可能不知道,其实它就是将查询结果集以XML形式展现,有了它我们可以简化我们的查询语句实现一些以前可能需要借助函数活存储过程来完成的工作.那么以一个实例为主 ...

  3. cpu对各种运算的速度对比

    今天忽然想到cpu对各种基本运算的速度对比,我对比了异或,加法和乘法,结果发现速度时间,加法小于乘法小于异或, 原本我以为异或会是最快的,结果异或是最慢的,这跟cpu中的alu算术逻辑单元的实现有关, ...

  4. R语言-处理异常值或报错的三个示例

    博客总目录:http://www.cnblogs.com/weibaar/p/4507801.html Tuesday, March 31, 2015 之前用rvest帮人写了一个定期抓取amazon ...

  5. thinkphp3.2.3关于模板使用之一二

    1.包含文件 使用场景:比如我们在编写网页布局的时候,可能每一个网页的头和脚是相同的,此时如果给每一个网页分别设置,未免太麻烦了.此时就可以使用带包含文件. 首先检查配置文件查看我们的主题目录在哪儿, ...

  6. Go - 数组 和 切片(array、slice)

    一.数组 与其他大多数语言类似,Go语言的数组也是一个元素类型相同的定长的序列. (1)数组的创建 数组有 3 种创建方式: 1) [length]Type 2) [length]Type{value ...

  7. java后端制作MD5加密

    由于一次业务的需要,我制作了一次密码的修改子业务. 当用户忘记密码的情况下,我需要动态的发给他一个6位的随机密码,通过即时通,短信,微信等.并同时修改数据库中的原密码为这6位的随机密码.让用户再去修改 ...

  8. hibernate中数据库方言

    在配置hibernate.cfg.xml时需指定使用数据库的方言: 例: <property name="dialect">org.hibernate.dialect. ...

  9. angularjs 笔记(1) -- 引导

    首先: 1,引入angularJS文件,<script type="text/javascript" src="angularjs.min.js"> ...

  10. WCF service 获取 client 端的 IP 和 port (转)

    转帖记录一下,以便日后使用. 主要使用是.NET3.5里的服务端上下文的消息实例的RemoteEndpointMessageProperty属性,获取客户端地址信息.但是限制 的绑定是HTTP.TCP ...