btrace记忆

上周五接近6个小时都在开会,悲剧阿。 美好的一天又这样被浪费了。

 

还好开会的时候自带了笔记本,闲来无聊又重新把btrace的内容重新梳理了一遍。

 

ps : 以前虽然看过btrace的使用,但根本是一种阅读者的态度,并没有反编译btrace源码进行查看。 还有就是实际也没写过几个btrace脚本,很多使用就显得很生疏。所以需要多加强下,只能多看过个2,3遍。

 

更详细,更精彩的一些btrace内容,请查看:  btrace一些你不知道的事(源码入手)

 

 

 

几个常用url : 

1. javadoc文档: http://btrace.kenai.com/javadoc/1.2/index.html

2. UserGuide :  http://kenai.com/projects/btrace/pages/UserGuide

3. DeveloperGuide : http://kenai.com/projects/btrace/pages/DeveloperGuide

4. jvisualvm plugins :  http://visualvm.java.net/pluginscenters.html  , http://visualvm.java.net/plugins.html

 

 

 

几个使用注意点:

1.  Kind.CALL 和 Kind.ENTRY的使用理解

  • Kind.ENTRY意指进入匹配probe点,跟你@Location设置的clazz和method没有任何关系。
  • Kind.CALL意指从某个匹配probe的方法中调用了匹配A class method的点,一定要和clazz,method配合使用。clazz和method的默认值为"",所以不能被匹配。

说白了一个就是跟踪A和B的调用关系,另一个只是关注调用了B的方法。

2.  @ProbeClassName 和 @ProbeMethodName的理解

因为btrace的probe点,clazz和method都支持正则匹配,clazz还支持super class or inteface匹配。所以对应匹配该probe的点会不同。

  • @ProbeClassName :  就是具体匹配对应的clazz规则的class name。如果没配置正则,则就是Probe clazz自己。
  • @ProbeMethodName :  就是具体匹配对应的method规则的method name。如果没配置正则,则就是Probe method自己。

3.  @TargetInstance 和 @TargetMethodOrField的理解

这个可以结合Kind.CALL进行说明,如果是probe A class的方法中调用了匹配B class。 @TargetInstance 返回的就是B class的实例,@Self返回的就是A class

  • @TargetInstance : 就是probe点内部间接调用class的对象引用
  • @TargetMethodOrField : 就是probe点内部间接调用class的方法或者对象属性。

说明: @TargetInstance和@TargetMethodOrField,必须结合Kind.CALL模式进行使用,具体原因看一下其代表的意思也就很明确了。 

4.  @Return , @Duration  和 方法参数AnyType的理解

可以理解下,我们常见的日志记录的需求,一般要求记录请求参数和返回结果,再加上对应的处理时间。那这时@Return , @Duration就派上用场了

  • @Return : 就是获取方法的返回对象。
  • @Duration :  就是整个Probe method调用所耗费的时间,单位us。
  • AnyType :  就是获取对应请求的参数,可以泛指任意类型。 同样你如果明确参数对象的,可以强制指定具体参数的类型

一般常见的使用: public static void log(@Return Object result, Object proxy, Method method, Object[] args, @Duration long durationL) 

说明: @Return和@Duration,必须结合Kind.Return模式进行使用,具体原因也挺明确了

5. @OnEvent的理解

就是和命令行进行交互,对事件的响应处理。比如btrace运行后,通过Ctrl + C指令,会有如下提示:

1.Please enter your option:
2.    1. exit
3.    2. send an event
4.    3. send a named event

如果你选择2或者3,就是对btrace client发起一个event事件。也挺好理解的

1.@OnEvent
2. public static void event() {
3.     println("event");
4. }
5.
6. @OnEvent("A")  // 相应name A event
7. public static void eventA() {
8.     println("eventA");
9. }
10.
11. @OnEvent("B") // 相应name B event
12. public static void eventB() {
13.     println("eventB");
14. }

说明: 一般可通过event事件,控制一下输出统计的内容信息。

 

6. @OnExit的理解

老实说,我也并不是非常理解。只知道通过OnExit可以监控btrace脚本发起的exit()调用,在btrace client退出之前做点事情。暂没想到特定的应用场景,数据清理?

1.@OnExit
2. public static void onexit(int code) {
3.     println("exit");
4. }
5.
6. @OnTimer(1000)
7. public static void ontime() {
8.     println(i++);
9.     if (i == 5) {
10.         println("do exit");
11.         exit(0);
12.     }
13. }

推荐jvisualvm btrace GUI

1. 启动,关闭,Event事件发送都挺方便的。

2. 不用每次vi 打开java文件进行编辑,修改script就方便多了

常用btrace监控脚本: 

1.  Jetty监控request/response buffer,有项目在使用中发现出现http 413错误(Request entity too large) , http://www.checkupdown.com/status/E413_cn.html

 

   初步怀疑是和buffer参数有关,原先使用jboss的参数为maxHttpHeadSize=8196,所以写了脚本提取了下线上的jetty参数,后面就修改了jetty参数为8k,解决了问题

1.@BTrace
2.public class JettyHeadBufferTracer {
3.
4.    @OnMethod(clazz = "org.eclipse.jetty.http.HttpBuffers", method = "/.*get.*Buffers/", location = @Location(value = Kind.ENTRY))
5.    public static void bufferMonitor(@Self Object self) {
6.        Field requestBuffersField = field("org.eclipse.jetty.http.HttpBuffers", "_requestBuffers");
7.        Field responseBuffersField = field("org.eclipse.jetty.http.HttpBuffers", "_responseBuffers");
8.
9.        Field bufferSizeField = field("org.eclipse.jetty.io.ThreadLocalBuffers", "_bufferSize");
10.        Field headerSizeField = field("org.eclipse.jetty.io.ThreadLocalBuffers", "_headerSize");
11.        Object requestBuffers = get(requestBuffersField, self);
12.        int requestBufferSize = (Integer) get(bufferSizeField, requestBuffers);
13.        int requestHeaderSize = (Integer) get(headerSizeField, requestBuffers);
14.        Object responseBuffers = get(responseBuffersField, self);
15.        int responseBufferSize = (Integer) get(bufferSizeField, responseBuffers);
16.        int responseHeaderSize = (Integer) get(headerSizeField, responseBuffers);
17.
18.        println(strcat(strcat(strcat("requestBufferSize : ", str(requestBufferSize)), " requestHeaderSize : "),
19.                       str(requestHeaderSize)));
20.        println(strcat(strcat(strcat("responseBufferSize : ", str(responseBufferSize)), " responseHeaderSize : "),
21.                       str(responseHeaderSize)));
22.    }
23.}

结果:

1.requestBufferSize : 8192 requestHeaderSize : 6144
2.responseBufferSize : 12288 responseHeaderSize : 6144

2. 项目中使用了dbcp做为数据库连接池,但对于连接池大小是否够用没有很直观的数据可以提供,所以写了个脚本提取一下数据

主要的数据内容:

   * maxActive(最大连接池大小),numActive(目前处于使用中),numIdle(处于空闲状态的连接数)

   * maxTotal(开启ps的最大值),totalActive(目前处于使用ps的总数),keyActive(当前sql的ps使用数),keyIdle(当前sql的ps空闲数)  针对开启了ps cache

1.<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
2.....
3.    <property name="poolPreparedStatements" value="true" />
4.    <property name="maxOpenPreparedStatements" value="10" />
5.....
6.</bean>
1.@BTrace
2.public class DbcpTracer {
3.
4.    @OnMethod(clazz = "org.apache.commons.pool.impl.GenericObjectPool", method = "/.*Object/", location = @Location(value = Kind.ENTRY))
5.    public static void poolMonitor(@Self Object self) {
6.        Field maxActiveField = field("org.apache.commons.pool.impl.GenericObjectPool", "_maxActive");
7.        Field numActiveField = field("org.apache.commons.pool.impl.GenericObjectPool", "_numActive");
8.        Field poolField = field("org.apache.commons.pool.impl.GenericObjectPool", "_pool");
9.        Field sizeField = field("org.apache.commons.pool.impl.CursorableLinkedList", "_size");
10.        int maxActive = (Integer) get(maxActiveField, self);
11.        int numActive = (Integer) get(numActiveField, self);
12.        int numIdle = (Integer) get(sizeField, get(poolField, self));
13.
14.        println(strcat(strcat(strcat(strcat(strcat("maxActive : ", str(maxActive)), " numActive : "), str(numActive)),
15.                              " numIdle : "), str(numIdle)));
16.    }
17.
18.    @OnMethod(clazz = "org.apache.commons.pool.impl.GenericKeyedObjectPool", method = "/.*Object/", location = @Location(value = Kind.ENTRY))
19.    public static void psMonitor(@Self Object self, Object key) {
20.        Field maxTotalField = field("org.apache.commons.pool.impl.GenericKeyedObjectPool", "_maxTotal"); // connectio的maxActive
21.        Field totalActiveField = field("org.apache.commons.pool.impl.GenericKeyedObjectPool", "_totalActive"); // connectio的active
22.        Field poolMapField = field("org.apache.commons.pool.impl.GenericKeyedObjectPool", "_poolMap"); // connectio的active
23.
24.        Field keyActiveField = field("org.apache.commons.pool.impl.GenericKeyedObjectPool$ObjectQueue", "activeCount"); // key的active
25.        Field keyIdleField = field("org.apache.commons.pool.impl.GenericKeyedObjectPool$ObjectQueue", "queue"); // key的idle
26.        Field keyIdleSizeField = field("org.apache.commons.pool.impl.CursorableLinkedList", "_size");
27.
28.        Field sqlField = field("org.apache.commons.dbcp.PoolingConnection$PStmtKey", "_sql");
29.
30.        int maxTotal = (Integer) get(maxTotalField, self);
31.        int totalActive = (Integer) get(totalActiveField, self);
32.        Map<Object, Object> poolMap = (Map<Object, Object>) get(poolMapField, self);
33.        int keyActive = 0, keyIdle = 0;
34.        if (poolMap != null) {
35.            Object queue = get(poolMap, key);
36.            if (queue != null) { // ObjectQueue
37.                keyActive = (Integer) get(keyActiveField, queue);
38.                keyIdle = (Integer) get(keyIdleSizeField, get(keyIdleField, queue));
39.            }
40.        }
41.        println(strcat(strcat(strcat(strcat(strcat(strcat(strcat("maxTotal : ", str(maxTotal)), " totalActive : "),
42.                                                   str(totalActive)), " keyActive : "), str(keyActive)), " keyIdle "),
43.                       str(keyIdle)));
44.
45.        println(strcat("Ps Key: ", str(get(sqlField, key))));
46.    }
47.
48.}
时间: 2024-10-27 04:17:40

btrace记忆的相关文章

btrace一些你不知道的事(源码入手)

背景     周五下班回家,在公司班车上觉得无聊,看了下btrace的源码(自己反编译). 一些关于btrace的基本内容,可以看下我早起的一篇记录:btrace记忆      上一篇主要介绍的是btrace的一些基本使用以及api,这里我想从btrace源码本身进行下介绍.至于btrace的优势,能用来干些什么,自己上他的官网看下或者google一下,花个半小时就能明白了.      至于为什么会去反编译查看btrace源码,主要是会在部门整个关于btrace的分享.同时btrace的相关技术

Btrace详细指南(JDK7,监控HashMap扩容)

背景     JAVA中如何排查疑难杂症,如何动态获取应用信息,我们有BTrace!     PS:集团有大杀器arthas,这里我们先从最原始最广泛的BTrace开始,后面可以玩玩Greys(开源,强于BTrace).     应用被tracle后,相关class会被改变,恢复需要重新编译,请自行把握. 一.下载安装BTtrace wiki:https://github.com/jbachorik/btrace/wiki BTrace博客:http://jbachorik.github.io/

微芯片植入大脑可保存人们的大脑记忆内容

据英国每日邮报报道,目前,一支美国研究小组认为,一种微芯片能够有助于建立受损大脑组织的记忆,预计未来两年内将植入志愿者大脑.来自南加州大学.维克森林大学的科学家研究分析海马体,这是大脑负责形成长期记忆(大约10年)的部分.他们认为能够计算出人类的记忆如何形成,从而植入芯片帮助局部大脑受损.中风和老年痴呆症患者恢复记忆. 至关重要的植入器:科学家研究分析海马体,它是大脑形成长期记忆的部分(图中红色部分),可保存大约10年的记忆 记忆地图:美国斯坦福大学进行的一项独立研究建立了老鼠大脑海马体的透明动

使Delphi程序记忆参数的设置

我们平时用的很多软件都具有一些记忆功能,如foxmail和TheBat等等. 这些软件能在启动时自动的保持上一次关闭软件时的一些状态,如窗口的初始位置,用户在软件中设置的一些特性(如窗口风格,横相排列还是竖相排列等等),如果能让我们的程序也具有这样的一些功能可以使我们程序看起来更专业性一些:) 这里我就来讲一下怎样使应用程序能记住上一次关闭时的窗口位置,并在下一次启动时和上一次的位置一样. 既然要保留信息,就一定要涉及到存贮的问题.数据的存贮有好几种办法,可以写.ini或.inf文件,还可以用D

hdu 1078 FatMouse and Cheese 记忆化搜索

  一开始打算正向用状态dp,结果果断超时,换成反向记忆话搜索就过了 /* author:jxy lang:C/C++ university:China,Xidian University **If you need to reprint,please indicate the source** */ #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #in

Flash广告记忆效果代码

当你常去的论坛上有个 Flash 广告,而你每次刷新页面的时候它都从头播放,会不会感觉很烦? 所以我们要改装一下这个Flash.给他植入记忆功能. 当你常去的论坛上有个 Flash 广告,而你每次刷新页面的时候它都从头播放,会不会感觉很烦? 所以我们要改装一下这个Flash.给他植入记忆功能. 要实现的效果: 刷新或关闭页面的时候记住上次的播放头位置. 下一次打开页面动画接着上一次的位置继续播放. 应用:效果可以看经典论坛的 Banner 广告. 实现代码如下(发布成AS1/AS2): var

技巧:Java中用动态代理类实现记忆功能

动态|技巧 记忆是衍生自Lisp,Python,和Perl等过程性语言的一种设计模式,它可以对前次的计算结果进行记忆. 一个实现了记忆功能的函数, 带有显式的cache, 所以, 已经计算过的结果就能直接从cache中获得, 而不用每次都进行计算. 记忆能显著的提升大计算量代码的效率. 而且是一种可重用的方案. 本文阐述了在Java中使用这一模式的方法,并提供了一个可以提供上述功能的"记忆类": Foo foo = (Foo) Memoizer.memoize(new FooImpl(

JAVA中用动态代理类实现记忆功能

动态 记忆是衍生自Lisp,Python,和Perl等过程性语言的一种设计模式,它可以对前次的计算结果进行记忆. 一个实现了记忆功能的函数, 带有显式的cache, 所以, 已经计算过的结果就能直接从cache中获得, 而不用每次都进行计算.记忆能显著的提升大计算量代码的效率. 而且是一种可重用的方案.本文阐述了在Java中使用这一模式的方法,并提供了一个可以提供上述功能的"记忆类": Foo foo = (Foo) Memoizer.memoize(new FooImpl()); 这

无限级目录树+记忆节点状态

特点: 1.无限级节点. 2.直接产生html代码,容易修改. 3.目录清楚,类似于资源管理器,(csdn论坛的,层数多了就不容易分清楚层次了). 4.记忆节点状态,人性化. 演示: http://www.yemaweb.com/demo/tree/ 下载: http://www.yemaweb.com/demo/tree/tree.rar 核心代码如下: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"