BTraceshell 打印变量中间变量

btrace使用实例 - 编程综合 - Tech - ITeye论坛
btrace使用实例
锁定老帖子
精华帖 (0) :: 良好帖 (7) :: 新手帖 (0) :: 隐藏帖 (0)
等级: 初级会员
来自: 杭州
发表时间:&&
最后修改:
是一个实时监控工具,使用了
java agent
jvm attach
技术,可以在不停机的情况下实时监控线上程序的运行情况,另外,对
脚本(实际上就是
程序)做了非常严格的安全限制,安全性很高,对应用程序基本没有影响。在性能方面,
进行过测试,对方法进行调用耗时统计的时候,基本消费在微秒级别,可以说微不足道。
上线过程后,发现了一个奇怪的现象,尽管“已知”的
发送端都已经迁移到
系统中,但是老的
系统仍然有新的
消息进来,因为连接
的服务器非常多,定位消息来源成了一个非常大的问题。这种情况,想到了使用
在某一台服务器进行线上监控进而期望发现这个幽灵。
首先,我们需要知道两个基本信息:消息类型和来源
,这样才可以定位
消息的来源。
要知道来源
,需要找到服务器端
管理的类,只有在建立
的地方,才可以抓到具体
,经过分析
代码,发现
连接基本是有下面这个类来服务所有消息的接收的:
public class TcpTransport extends TransportThreadSupport implements Transport, Service, Runnable {
private static final Log LOG = LogFactory.getLog(TcpTransport.class);
private static final ThreadPoolExecutor SOCKET_CLOSE;
protected final URI remoteL
protected final URI localL
protected final WireFormat wireF
protected int connectionTimeout = 30000;
protected int soT
protected int socketBufferSize = 64 * 1024;
protected int ioBufferSize = 8 * 1024;
protected boolean closeAsync=
protected S
这个类中包含一个
对象的成员变量,所有我们只要监控
readCommand
方法,这个方法的返回值实际上就是一个
ActivemqObjectMessage
对象,这样就可以在一个方法上加拦截器就可以同时捕获到
和消息对象,两全其美!!!
protected Object readCommand() throws IOException {
return wireFormat.unmarshal(dataIn);
消息通道都是一个队列
,所以无法通过队列名称来确定消息类型,必须通过
ESBTransferObject
对象来取得消息类型:
public class ESBTransferObject implements Serializable {
private static final long serialVersionUID = -5303878L;
* 消息体,原则上对象序列化后的XML数据(String) 注意使用XML1.1规范。
private Objec
* 用户自定义数据
private Object
userDefineD
* 目的消息类型
private int
但是,在服务器端并没有
ESBTransferObject
对象,无法反序列化(
也不支持反序列化操作),所以没有方法简单取得消息类型信息!!!
,我不反序列化,直接拿二进制
,类型信息应该是在固定位置的吧?但是发现这个对象
变长字符串定义在类型之前,类型位置不确定了,晕倒啊
不死心,输出二进制数据,柳暗花明啊,原来对象序列化的时候,
都是紧接着类型信息写入的,所以,类型信息是在固定位置的
,类型信息始终是
两个字节(实际上是
个字节,但是目前我们只占有
,编写代码,测试环境运行一下,晕倒,竟然有数组溢出!
,把这个数组打印下来(这个需要点技巧,
都不允许),竟然发现位置偏移到
,这个真的不知道什么原因,估计是客户端发送的时候压缩了,简单修改偏移量,测试运行,
,所有的消息类型和
的对照表打印出来了。
package com.alibaba.btrace.
import static com.sun.btrace.BTraceUtils.*;
import com.sun.btrace.annotations.*;
public class AMQQueue2IP {
@OnMethod(clazz = "org.apache.activemq.transport.tcp.TcpTransport",
//需要拦截的类名
method = "readCommand",
//需要拦截的方法名
location = @Location(Kind.RETURN))
//拦截位置,方法返回时
public static void onTransportCommandExit(@Self Object transport, @Return Object command) { //捕获调用对象和返回值
String commandName = str(command);
boolean isObjectMessage = (indexOf(commandName, "org.apache.activemq.command.ActiveMQObjectMessage") &= 0);
if (isObjectMessage) {
Object msg =
Object content = get(field(getSuperclass(getSuperclass(classOf(msg))), "content", false), msg);//捕获消息内容byte[]
byte[] bs = (byte[]) get(field(classOf(content), "data", false), content);
if (bs.length &= 206) {
int off = getInt(field(classOf(content), "offset", false), content);
int code = (0xff00&bs[205]&&8)+(0xff&bs[206]);
//转换205,206字节为消息类型
//println(str(code));
Object socket = get(field(classOf(transport), "socket"), transport);
String address = str(socket);
//截取ip地址
int s = indexOf(address, "/");
int e = indexOf(address, ",");
int len = e -
String ip = substr(address, s + 1, e);
print(strcat(timestamp(),"---"));
println(strcat(strcat("ip: ", ip), strcat(" queueName: ", str(code))));
打印结果:
2/3/10 12:38 PM---ip: 172.22.2.34 queueName: 2001
2/3/10 12:38 PM---ip: 172.22.2.41 queueName: 5001
2/3/10 12:38 PM---ip: 172.22.2.22 queueName: 5001
2/3/10 12:38 PM---ip: 172.22.2.47 queueName: 2001
2/3/10 12:38 PM---ip: 172.22.2.31 queueName: 2001
2/3/10 12:38 PM---ip: 172.22.2.13 queueName: 5001
2/3/10 12:38 PM---ip: 172.22.2.6 queueName: 5001
2/3/10 12:38 PM---ip: 172.22.2.48 queueName: 2001
2/3/10 12:38 PM---ip: 172.22.2.39 queueName: 2001
是一个强大的工具,但是,在线上检测的时候考虑时效性和安全性,必须有一个经过检验的脚本库才可以安全及时的定位系统问题.
文章: 1276
来自: 杭州
发表时间:&&
老庄也开始玩诊断了啊.
诊断是门艺术, 如何才能更科学呢~~ 我一直很烦恼.
请登录后投票
RednaxelaFX
积分: 1110
来自: 海外
发表时间:&&
hmm……这帖为什么不在Java区,差点漏掉了。最近我也在看BTrace相关,看看能不能用在这边的线上监控上。总有人担心字节码操纵不安全,诶。
请登录后投票
来自: 杭州
发表时间:&&
btrace是个好东西,维护好自己定制的一套脚本就很好用了
请登录后投票
等级: 初级会员
来自: 杭州
发表时间:&&
刚好也在研究BTrace的使用,结果找到的都是自己公司人的。
请登录后投票
Willam2004
等级: 初级会员
来自: 杭州
发表时间:&&
老庄写的很详细,刚好正在学习btrace。
请登录后投票
跳转论坛:移动开发技术
Web前端技术
Java企业应用
编程语言技术btrace一些你不知道的事(源码入手)【转】
时间: 02:03:53
&&&& 阅读:200
&&&& 评论:
&&&& 收藏:
标签:&&&&&&&&&&&&&&&&&&&&&&&&&&&from:http://agapple.iteye.com/blog/1005918背景&&& 周五下班回家,在公司班车上觉得无聊,看了下btrace的源码(自己反编译)。 一些关于btrace的基本内容,可以看下我早起的一篇记录:&&& 上一篇主要介绍的是btrace的一些基本使用以及api,这里我想从btrace源码本身进行下介绍。至于btrace的优势,能用来干些什么,自己上他的官网看下或者google一下,花个半小时就能明白了。&&& 至于为什么会去反编译查看btrace源码,主要是会在部门整个关于btrace的分享。同时btrace的相关技术文档缺乏,javadoc很多时候说的不明不白,作者也没有提供源码开源,所以就有了这次的分享。Btrace涉及相关技术asm&instrument&&&JVM TI(java tool api)&&Java Compiler Api&&&大家可以先去预备一下知识。&Btrace的大体设计下面来看一个Btrace的设计图:&&说明:&1. BtraceClient : 为我们使用的btrace的本地api,一般我们使用的bin/btrace会在本地启动一个btrace jvm,其内部使用了Java Complier Api, JVMTI技术,以及创建了一个socket。&Java Complier Api:动态的将我们传递的监控的java源文件动态编译成.class文件JVMTI: 主要是利用了java 1.6之后的VirtaulMachine技术,动态的attach到一个已启动的jvm上,为他去启动一个BtraceAgent。该Agent会为BtraceClient启动一个server socket进行通讯。(多进程之间的通讯)本地socket: BtraceClient和BtraceAgent之间的数据通讯,比如生成的.class发送到BtraceAgent,还有一些Event事件等等。BtraceAgent同样可以将服务端print()的数据通过socket的方式回传给BtraceClient进行打印2. BtraceAgent:为我们在目标jvm上植入的btrace agent实现。主要是Instrumentation技术, asm字节码处理技术。BtraceAgent的启动可以有两种方式: BtaceClient动态attach后进行启动, 另一种就是在目标jvm启动之前添加agent参数进行启动。BtraceAgent会启动一个server socket,与BtraceClient客户端进行交互,客户端可以将监控的.class文件通过socket发送,同样也可以在jvm启动时直接指定对应本地的.class做为监控脚本。BtraceAgent在接受到监控指令后,会遍历当前所有已经加载的class类,挨个进行匹配检查,并生成相应的监控字节码(监控方法)。&&btrace的包结构:btrace-client.jarbtrace-boot.jarbtrace-agent.jarbtrace-client&&&一般我们通常直接使用的命令,比如:&Java代码&&bin/btrace&$pid&Btrace.java&&&都是直接调用了btrace-client包中的代码。&几个核心类介绍:1. com.sun.btrace.client.Main (btrace的启动入口)&&& 调用Client进行complier(Java Compiler Api)和attach(JVM TI)处理2. com.sun.btrace.client.Clientcompiler方法 : 调用了Java Complier Api进行动态编译你的Btrace.java文件Java代码&&this.compiler&=&ToolProvider.getSystemJavaCompiler();&&&&this.stdManager&=&this.compiler.getStandardFileManager(null,&null,&null);&&&&&&&&&&&&Verifier&btraceVerifier&=&new&Verifier(this.unsafe);&//指定了btrace特定的语法校验器&&&&attach方法: 调用VirtualMachine.attach(pid);vm.loadAgent(agentPath, agentArgs);动态加载btrace-agent.jar包Java代码&&传递给agent程序的几个参数:&&&&&debug=true&&&&unsafe=true&&&&dumpClass=true&&&&dumpDir=xx&&&&trackRetransforms=true&&##是否记录instrument行为&&&&bootClassPath=&xx&##agent.jar使用&&&&systemClassPath&=xx&##agent.jar使用&&&&probeDescPath=xx&&&&&submit方法: 调用提交对应的instrument指令,并传递对应code的byte[]Java代码&&this.sock&=&new&Socket("localhost",&this.port);&&&&this.oos&=&new&ObjectOutputStream(this.sock.getOutputStream());&&&&...&&&&&&&&WireIO.write(this.oos,&new&InstrumentCommand(code,&args));&&&&&几点说明:*& &在调用了attach方法后,会通过btrace-agent.jar中的com.sun.btrace.agent.Main启动一个ServerSocketJava代码&&int&port&=&2020;&&&&String&p&=&(String)argMap.get("port");&&&&....&&&&ServerSocket&&&&&&&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自定义的语法校验器&Java代码&&Boolean&value&=&this.unsafe&?&Boolean.TRUE&:&(Boolean)ct.accept(new&VerifierVisitor(this),&null);&&//&注意下unsafe的判断&&&&&&4.& com.sun.btrace.compiler.VerifierVisitor (具体的一些检查规则)&visitBinary& String字符串的+限制&visitClass& class的检查,不允许有父类,不允许有接口类,不允许非static变量,必须有Btrace @标签&visitDoWhileLoop 不允许do while循环&visitForLoop 不允许for循环&visitMethod 必须为static public ,不允许出现synchronized标记&visitNewArray 不允许出现new Array&visitNewClass 不允许出现new 对象&visitReturn 不允许有返回值&visitSynchronized 不允许有同步快&visitThrow visitTry 不允许有try catch的动作&visitOther 除上面允许之外的,不允许有其他的&说明:*& 看完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()方法main方法: 首先解析参数,然后会启动一个agentThread(Daemon线程)parseArgs : 对应的参数解析,客户端在attach时,提交给agent后的一些参数Java代码&&bootClassPath=xx.jar&&//需要动态增加的jar&&&&systemClassPath=xx.jar&&&&noServer=true/false&//是否启动server&socket&&&&debug=true/false&&&&unsafe=true/false&&&&dumpClasses=true/false&&&&dumpDir=路径&&&&trackRetransforms=true/false&&&&probeDescPath=路径&&&&stdout=true/false&&&&&script=文件&&&&scriptdir=路径&&&&scriptOutputFile=文件路径特别注意下相比于Btrace-client提交的参数中,多了几个script,scriptdir等参数,允许在Client调用服务端一个指定的Btrace&script文件进行处理&&&&&&&loadBTraceScript : 装载指定的script(注意是script和scriptDir中指定的script),必须是.class文件,会调用FileClient进行处理,最后调用handleNewClient进行统一处理,最后调用handleNewClient进行统一instrument处理。startServer : main启动的agentThread会调用该方法,这里会启动一个serversocket,和btrace-client的客户端socket进行通讯,使用RemoteClient,最后调用handleNewClient进行统一instrument处理。handleNewClient : 启动一个异步线程进行class Transformer,根据提交的byte[] code进行类文件重写说明:*&目前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文件)两者的不同无非就是对应的结果输出方式不同,一个是传回给客户端,另一个是直接终端输出会调用Client.loadClass()进行btrace数据解析,主要是解析对应的OnMethod和OnProbe数据。3. com.sun.btrace.agent.ProbeDescriptorLoader会解析对应Btrace script中出现的@OnProbe,解析xml文件中对应的@OnMethod信息4. com.sun.btrace.agent.Client:& (RemoteClient和FileClient的共同父类)instument中的Transformer的实现类loadClass()方法: btrace script脚本解析verify 首先进行class的校验, 调用Verity类进行检查(可手工执行:java com.sun.btrace.runtime.Verifier &.class file&)runtime.defineClass(codeBuf); 使用反射重新装载class bytetransform: 核心的方法(isBTraceClass(cname)) || (isSensitiveClass(cname)) 过滤btrace内部类,已经一些Object,ThreadLocal,sun/reflect类)instrument方法 : 方法中调用asm的ClassReader进行class对象解析,并设置Instrumentor进行Class对象处理5.&&com.sun.btrace.runtime.Instrumentor&: 是Btrace实现代码监控增强处理的核心逻辑可以直接调用:Java代码&&java&com.sun.btrace.runtime.Instrumentor&&btrace-class&&&target-class&]&&&&&&Btrace的几点总结1. btrace支持的监控方式本地jvm监控:目前大多数都是用的是btrace和监控的目标java是在同一机器上远程jvm监控:需要在远程服务器启动时添加btrace-agent.jar,需要重写btrace客户端,完成和serversocket建立通讯,完成btrace script发送监控。1.&VirtualMachine动态attach不支持远程操作,所以无法动态的进行agent添加。2. btrace支持的jdk版本java 1.4以及之前 : 不支持,Instrument在jdk 1.5之后才出现。java 1.5 :&必须手动在jvm启动时添加btrace-agent.jar,因为VirtualMachine是在jdk 1.6之后才出现。java 1.6 : 推荐使用agent启动:&Java代码&&java&-Xshare:off&-javaagent:${BTRACE_HOME}/build/btrace-agent.jar=dumpClasses=false,debug=false,unsafe=false,probeDescPath=.,noServer=true,script=$1&&&&具体的参数见上面的代码分析&&&&3.&btrace的支持的script方式有多种。client上的.java文件会进行动态编译,会有比较多的语法限制,btrace一堆的你不能做的事client上的.class文件没什么好讲的,自己写Btrace script时导入btrace-client.jar,写好后生成一个.class文件,再通过btrace pid&Btrace.class进行启动。&remote上的.class文件1.&修改btrace-client中的Client类,支持script和scriptDir的一些参数提交。2. 在remote机器上放置对应的btrace.class文件4. btrace的使用是否会对java进程造成影响?(影响是肯定的,不过影响不大)&装载时的影响:btrace每次使用,都会重新load所有的class。当然如果OnMethod不匹配,是不会被重新装载。所以跟你的OnMethod的匹配规则很有关系,如果使用+java.lang.Object。那就死定了。退出后的影响:btrace监控每次退出后,原先所有的class都不会被恢复,你的所有的监控代码依然一直在运行&抓取了下btrace改写过后的类:Java代码&&public&InstrumentServer(String&ip,&String&port)&&&&{&&&&&&$btrace$com$agapple$btrace$Instrumentor$InstrumentTracer$bufferMonitor(this);&&&&&&this.ip&=&&&&&&&this.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)) 再看一下BTraceRuntime中对应方法的实现:&Java代码&&private&volatile&boolean&&&&&public&static&boolean&enter(BTraceRuntime&current)&&&&{&&&&&&if&(current.disabled)&return&false;&&&&&&return&map.enter(current);&&&&}&&每次执行你的监控代码之前会先进行一个判断,判断当前是否处于监控中。你的客户端发起了exit指令后,该方法判断false,直接return。所以btrace使用退出后会让你的代码多走了一个方法调用+一个对象属性判断,所以说影响还是非常的少&5. btrace诸多的使用限制,你必须得知道:&Java代码&&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.&&&说明:&&在btrace-client和btrace-agent分别都有对诸多限制的检查。btrace-client代码类:&btrace-agent代码类:&补充说明:&正因为btrace有这诸多的限制,才可以让我们的监控代码可以更加的放心,这也正是btrace能普及的一个很重要的原因。不得不说的一个点:对String的"+"限制使用,让我们使用起来很不爽,不过还好在btrace 1.2之后,作者提供了一个StringBuilder。相比于strcat已经好用多了6. btrace对string字符串的处理可以参看总结3,突破对应的限制。不是非常建议,因为总结4中提出即使btrace client退出后,服务端一直会运行btrace script。所以一旦有写的动作,会是一个长期持续的过程btrace 1.2 release说明中,已经提到增加了StringBuilder进行字符串处理,至少比先前的strcat使用上已经方便很多了。具体查看:7. btrace的相关源码:官网上找到一个,不过是web版本:附件中自己使用了jd-gui反编译生成了一个。8. btrace中对OnMethod的Location使用上,以及一些annotation使用不明确,可以查看:&说明: self, ProbeClassName , ProbeMethodName 在任何的Kind中都支持,所以就不在每个表格中赘述。KindWhere.BEFOREWhere.AFTERARRAY_GET数组长度(int) , 数组类型(type)@return , 数组长度(int) , 数组类型(type)ARRAY_SET原始数组类型(type) , 数组长度(int) , 目标数组类型(type)@return,原始数组类型(type) , 数组长度(int) , 目标数组类型(type)CALL方法参数 , @TargetInstance , @TargetMethodOrField方法参数,&@return , @TargetInstance , @TargetMethodOrFieldCATCH异常类型(type)异常类型(type)CHECKCAST&转型的目标类型转型的目标类型ENTRY方法参数方法参数&ERROR异常类型(throwable type)异常类型(throwable type)FIELD_GET@TargetInstance,@TargetMethodOrField@TargetInstance,@TargetMethodOrField,@return&FIELD_SETfldValueIndex,@TargetInstance,@TargetMethodOrFieldfldValueIndex,@TargetInstance,@TargetMethodOrField&INSTANCEOF转型的目标类型转型的目标类型&LINE行数&行数&NEW对象类名&@returnNEWARRAY数组内部对象类名,类名数组内部对象类名,类名, @return&RETURN无参数,@return , @DurationSYNC_ENTRYsync对象sync对象SYNC_EXITsync对象sync对象THROW异常类型异常类型&&最后花了多个小时时间整理了这份blog,希望能给大家理解btrace,掌握btrace的使用能带来一些帮助!!&&有问题和交流,欢迎站内联系&(117.3 KB)下载次数: 190&(139.1 KB)下载次数: 187分享到:&&&|& 00:25浏览 6230论坛回复 /&&(10 / 11166)分类:评论10 楼&&&&xiuyuandashi 写道博主你好,&&& 我想请教下,你是如何分析btrace,透彻了解btrace的工作机制的。多看看btrace的源码9 楼&&&&博主你好,&&& 我想请教下,你是如何分析btrace,透彻了解btrace的工作机制的。8 楼&&&&命中注定1314 写道确实阿 ,现在暂时想的不用BTrace的远程agent, 自己用Socket来传输, 监控那边还是像本地那样干, 你改过他的Agent和Client咯?暂时没,都是直接在服务器上运行btrace7 楼&&&&确实阿 ,现在暂时想的不用BTrace的远程agent, 自己用Socket来传输, 监控那边还是像本地那样干, 你改过他的Agent和Client咯?6 楼&&&&命中注定1314 写道师兄你修改过远程的Btrace吗你需要做远程监控?5 楼&&&&师兄你修改过远程的Btrace吗4 楼&&&&anxiety 是曹帅写的吗?求源码地址~3 楼&&&&RednaxelaFX 写道agapple 写道至于为什么会去反编译查看btrace源码,主要是会在部门整个关于btrace的分享。同时btrace的相关技术文档缺乏,javadoc很多时候说的不明不白,作者也没有提供源码开源,所以就有了这次的分享。&7. btrace的相关源码:&官网上找到一个,不过是web版本:附件中自己使用了jd-gui反编译生成了一个。呃…明明是GPLv2开源的。源码用管理着。&要源码的话这样就好了:&Command prompt代码&&hg&clone&https://hg.kenai.com/hg/btrace~hg&&正常的话会看到:&Command prompt代码&&$&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,长见识了&&&2 楼&&&&agapple 写道至于为什么会去反编译查看btrace源码,主要是会在部门整个关于btrace的分享。同时btrace的相关技术文档缺乏,javadoc很多时候说的不明不白,作者也没有提供源码开源,所以就有了这次的分享。&7. btrace的相关源码:&官网上找到一个,不过是web版本:附件中自己使用了jd-gui反编译生成了一个。呃…明明是GPLv2开源的。源码用管理着。&要源码的话这样就好了:&Command prompt代码&&hg&clone&https://hg.kenai.com/hg/btrace~hg&&正常的话会看到:&Command prompt代码&&$&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&&代码就抓下来了…1 楼&&&&貌似关注btrace的人挺少,呵呵。&用btrace最大的好处就是监控业务数据,而且允许在jvm运行之后动态attach,完全是一种无嵌入的监控模式。你不需要像jwebap一样,丢个jar包到你的运行容器中。&一般常用: &1. 某方法调用的性能监控&2. 某方法调用的参数内容监控,记录等。(排查问题特别有用)&3. ......标签:&&&&&&&&&&&&&&&&&&&&&&&&&&&原文:http://www.blogjava.net/xiaomage234/archive//428731.html
教程昨日排行
&&国之画&&&& &&&&&&
&& &&&&&&&&&&&&&&
鲁ICP备号-4
打开技术之扣,分享程序人生!

我要回帖

更多关于 linux 打印环境变量 的文章

 

随机推荐