锁定老帖子 主题:btrace一些你不知道的事(源码入手)
该帖已经被评为精华帖
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
作者 | 正文 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
发表时间:2011-04-18
最后修改:2011-04-18
背景周五下班回家,在公司班车上觉得无聊,看了下btrace的源码(自己反编译)。 一些关于btrace的基本内容,可以看下我早起的一篇记录:btrace记忆
上一篇主要介绍的是btrace的一些基本使用以及api,这里我想从btrace源码本身进行下介绍。至于btrace的优势,能用来干些什么,自己上他的官网看下或者google一下,花个半小时就能明白了。
至于为什么会去反编译查看btrace源码,主要是会在部门整个关于btrace的分享。同时btrace的相关技术文档缺乏,javadoc很多时候说的不明不白,作者也没有提供源码开源,所以就有了这次的分享。 Btrace涉及相关技术
大家可以先去预备一下知识。
Btrace的大体设计下面来看一个Btrace的设计图:
说明: 1. BtraceClient : 为我们使用的btrace的本地api,一般我们使用的bin/btrace会在本地启动一个btrace jvm,其内部使用了Java Complier Api, JVMTI技术,以及创建了一个socket。
2. BtraceAgent:为我们在目标jvm上植入的btrace agent实现。主要是Instrumentation技术, asm字节码处理技术。
btrace的包结构:
btrace-client 一般我们通常直接使用的命令,比如:
bin/btrace $pid Btrace.java
都是直接调用了btrace-client包中的代码。
几个核心类介绍: 1. com.sun.btrace.client.Main (btrace的启动入口)
2. com.sun.btrace.client.Client
几点说明: * 在调用了attach方法后,会通过btrace-agent.jar中的com.sun.btrace.agent.Main启动一个ServerSocket int port = 2020; String p = (String)argMap.get("port"); .... ServerSocket ss; try { (isDebug()) debugPrint(new StringBuilder().append("starting server at ").append(port).toString()); System.setProperty("btrace.port", String.valueOf(port)); if ((scriptOutputFile != null) && (scriptOutputFile.length() > 0)) { System.setProperty("btrace.output", scriptOutputFile); } ss = new ServerSocket(port); } catch(Exception e) .... while (true) { if (!isDebug()) continue; debugPrint("waiting for clients"); Socket sock = ss.accept(); if (!isDebug()) continue; debugPrint(new StringBuilder().append("client accepted ").append(sock).toString()); Client client = new RemoteClient(inst, sock); handleNewClient(client); continue; }
* 所以在submit中,会通过一个本地socket进行连接server,并提交相应的Btrace.java中的监控代码(这时应该是编译后的字节码).
3. com.sun.btrace.compiler.Verifier btrace自定义的语法校验器
4. com.sun.btrace.compiler.VerifierVisitor (具体的一些检查规则)
说明: * 看完Verifier和VerifierVisitor后,相信大家都应该明白了Btrace所谓的诸多限制,只是针对.java需要动态编译。如果我们预先生成.class文件,Btrace在1.2版本中并不会作类型合法性检查。(在将code发送给btrace-agent后,会在目标的jvm内部进行一次简单的Btrace语法检查,具体见后面Btrace-agent介绍)
5. com.sun.btrace.comm.XXX Btrace的各种command指令
btrace-agent 大致了解了Client类中的attach和submit方法后,相信也能猜到对应agent的一些设计。简单的看一下
1. com.sun.btrace.agent.Main 为attach上之后agent的总入口,会调用agentmain()方法
说明: * 目前instrument进行字节码重写时,会重新load所有的class进行处理。(Btrace可以使用正则,父类的方式进行匹配,只能是挨个Class进行处理,看下是否有匹配的OnMethod) * 相比于btrace-client提交过来的参数中,btrace-agent支持的参数中多了几个script,scriptdir等,允许在Client调用服务端一个指定的Btrace script文件进行处理,注意这里的script必须是编译后的.class文件。和通过socket提交的btrace在处理上没有太大的差异。
2. com.sun.btrace.agent.RemoteClient / FileClient : (RemoteClient为通过socket提交的script , FileClient为script和scriptDir指定的script文件)
3. com.sun.btrace.agent.ProbeDescriptorLoader
4. com.sun.btrace.agent.Client: (RemoteClient和FileClient的共同父类)
5. com.sun.btrace.runtime.Instrumentor : 是Btrace实现代码监控增强处理的核心逻辑 可以直接调用: java com.sun.btrace.runtime.Instrumentor <btrace-class> <target-class>]
Btrace的几点总结1. btrace支持的监控方式
2. btrace支持的jdk版本
agent启动:
java -Xshare:off -javaagent:${BTRACE_HOME}/build/btrace-agent.jar=dumpClasses=false,debug=false,unsafe=false,probeDescPath=.,noServer=true,script=$1 具体的参数见上面的代码分析 3. btrace的支持的script方式有多种。
4. btrace的使用是否会对java进程造成影响?(影响是肯定的,不过影响不大)
装载时的影响:
退出后的影响:
抓取了下btrace改写过后的类:
public InstrumentServer(String ip, String port) { $btrace$com$agapple$btrace$Instrumentor$InstrumentTracer$bufferMonitor(this); this.ip = ip; this.port = port; } private static void $btrace$com$agapple$btrace$Instrumentor$InstrumentTracer$bufferMonitor(@Self Object arg0) { if (!BTraceRuntime.enter(InstrumentTracer.runtime)) return; try { Field ipField = BTraceUtils.field("com.agapple.btrace.Instrumentor.InstrumentServer", "ip"); Field portField = BTraceUtils.field("com.agapple.btrace.Instrumentor.InstrumentServer", "port"); String ip = (String)BTraceUtils.get(ipField, self); String port = (String)BTraceUtils.get(portField, self); BTraceUtils.println(BTraceUtils.strcat(BTraceUtils.strcat(BTraceUtils.strcat("ip : ", BTraceUtils.str(ip)), " port : "), BTraceUtils.str(port))); BTraceRuntime.leave(); return; } catch (Throwable localThrowable) { BTraceRuntime.handleException(localThrowable); } } 注意其中的if (!BTraceRuntime.enter(InstrumentTracer.runtime)) return;
再看一下BTraceRuntime中对应方法的实现:
private volatile boolean disabled; public static boolean enter(BTraceRuntime current) { if (current.disabled) return false; return map.enter(current); } 每次执行你的监控代码之前会先进行一个判断,判断当前是否处于监控中。你的客户端发起了exit指令后,该方法判断false,直接return。
所以btrace使用退出后会让你的代码多走了一个方法调用+一个对象属性判断,所以说影响还是非常的少
5. btrace诸多的使用限制,你必须得知道:
can not create new objects. can not create new arrays. can not throw exceptions. can not catch exceptions. can not make arbitrary instance or static method calls - only the public static methods of com.sun.btrace.BTraceUtils class or methods declared in the same program may be called from a BTrace program. (pre 1.2) can not have instance fields and methods. Only static public void returning methods are allowed for a BTrace class. And all fields have to be static. can not assign to static or instance fields of target program's classes and objects. But, BTrace class can assign to it's own static fields ("trace state" can be mutated). can not have outer, inner, nested or local classes. can not have synchronized blocks or synchronized methods. can not have loops (for, while, do..while) can not extend arbitrary class (super class has to be java.lang.Object) can not implement interfaces. can not contains assert statements. can not use class literals.
说明:
补充说明:
6. btrace对string字符串的处理
7. btrace的相关源码:
8. btrace中对OnMethod的Location使用上,以及一些annotation使用不明确,可以查看:http://kenai.com/projects/btrace/sources/hg/content/src/share/classes/com/sun/btrace/runtime/Instrumentor.java
说明: self, ProbeClassName , ProbeMethodName 在任何的Kind中都支持,所以就不在每个表格中赘述。
最后花了多个小时时间整理了这份blog,希望能给大家理解btrace,掌握btrace的使用能带来一些帮助!!
有问题和交流,欢迎站内联系 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
发表时间:2011-06-23
貌似关注btrace的人挺少,呵呵。
用btrace最大的好处就是监控业务数据,而且允许在jvm运行之后动态attach,完全是一种无嵌入的监控模式。你不需要像jwebap一样,丢个jar包到你的运行容器中。 一般常用: 1. 某方法调用的性能监控 2. 某方法调用的参数内容监控,记录等。(排查问题特别有用) 3. ...... |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
发表时间:2011-06-23
最后修改:2011-06-23
agapple 写道 至于为什么会去反编译查看btrace源码,主要是会在部门整个关于btrace的分享。同时btrace的相关技术文档缺乏,javadoc很多时候说的不明不白,作者也没有提供源码开源,所以就有了这次的分享。
7. btrace的相关源码:
呃…BTrace明明是GPLv2开源的。源码用Mercurial管理着。 要源码的话这样就好了: hg clone https://hg.kenai.com/hg/btrace~hg 正常的话会看到: $ hg clone https://hg.kenai.com/hg/btrace~hg destination directory: btrace~hg requesting all changes adding changesets adding manifests adding file changes added 421 changesets with 2192 changes to 692 files (+4 heads) updating working directory 299 files updated, 0 files merged, 0 files removed, 0 files unresolved 代码就抓下来了… |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
发表时间:2011-06-24
RednaxelaFX 写道 agapple 写道 至于为什么会去反编译查看btrace源码,主要是会在部门整个关于btrace的分享。同时btrace的相关技术文档缺乏,javadoc很多时候说的不明不白,作者也没有提供源码开源,所以就有了这次的分享。
7. btrace的相关源码:
呃…BTrace明明是GPLv2开源的。源码用Mercurial管理着。 要源码的话这样就好了: hg clone https://hg.kenai.com/hg/btrace~hg 正常的话会看到: $ hg clone https://hg.kenai.com/hg/btrace~hg destination directory: btrace~hg requesting all changes adding changesets adding manifests adding file changes added 421 changesets with 2192 changes to 692 files (+4 heads) updating working directory 299 files updated, 0 files merged, 0 files removed, 0 files unresolved 代码就抓下来了… 呵呵,我土了, 先前不了解mercurial工具。 只用过svn和git,长见识了 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
发表时间:2011-10-13
正打算试用一下,就发现了这篇好文章,谢谢分享了
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
发表时间:2011-10-20
window下BTrace能运行吗?貌似不支持哦....
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
发表时间:2011-10-20
cectsky 写道 window下BTrace能运行吗?貌似不支持哦....
技术原理上应该都是支持的,java写的,没用so库 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
发表时间:2011-10-20
好文章~慢慢品尝
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
发表时间:2011-11-08
非常实用
agapple有没有打算重新封装下它的代码? |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
发表时间:2012-04-13
onMethod 中的 location=@location(kind.return)表示被注解的方法在 指定方法返回时执行吗
那么 kind.call 是被注解的方法 在指定方法被掉用时 执行吗 QQ 345648043 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||