占小狼 转载请注明原创出处,谢谢!

背景

记得前几天有人问我:在生产环境中可能经常遇到各种问题,你们一般是如何进行调试的? 很惭愧,没有经验。因为平时碰不到生产环境的服务器,定位问题需要各种数据,所以大多数问题的解决方式都是在本地打断点进行调试,或者在测试环境利用输出日志进行调试,这种方式简单粗暴,但过程比较繁琐,需要各种重新发布,重启应用,还不能保证一次就找到问题的根源。直到最近才了解到Btrace这个工具,对于这样一个神器,我觉得有必要记录一篇,让更多的人知道。

Btrace

BTrace是sun公司推出的一款Java 动态、安全追踪(监控)工具,可以在不用重启的情况下监控系统运行情况,方便的获取程序运行时的数据信息,如方法参数、返回值、全局变量和堆栈信息等,并且做到最少的侵入,占用最少的系统资源。

项目地址:Btrace
用户指南:UserGuide

由于Btrace会把脚本逻辑直接侵入到运行的代码中,所以在使用上做很多限制:
1、不能创建对象
2、不能使用数组
3、不能抛出或捕获异常
4、不能使用循环
5、不能使用synchronized关键字
6、属性和方法必须使用static修饰

根据官方声明,不恰当的使用BTrace可能导致JVM崩溃,如在BTrace脚本使用错误的class文件,所以在上生产环境之前,务必在本地充分的验证脚本的正确性。

Btrace可以做什么?

1、接口性能变慢,分析每个方法的耗时情况;
2、当在Map中插入大量数据,分析其扩容情况;
3、分析哪个方法调用了System.gc(),调用栈如何;
4、执行某个方法抛出异常时,分析运行时参数;
5、....

Btrace第一个例子

package com.metty.rpc.common;
import java.util.Random; /**
* Created by j_zhan on 2016/11/28.
*/
public class BtraceCase {
public static Random random = new Random();
public int size; public static void main(String[] args) throws Exception {
new BtraceCase().run();
} public void run() throws Exception {
while (true) {
add(random.nextInt(10), random.nextInt(10));
}
} public int add(int a, int b) throws Exception {
Thread.sleep(random.nextInt(10) * 100);
return a + b;
}
}

执行add方法时,对传入参数、返回值以及执行耗时进行分析,btrace脚本:

 
 

通过jps命令获取pid为8454
执行btrace 8454 Debug.java实现对运行代码的监控,输出结果如下:

 
 

可以发现,Btrace可以获取每次执行add方法时的数据,当然Btrace能做的远远不止这些,比如获取当前jvm堆使用情况、当前线程的执行栈等等。

参数说明

@OnMethod

Btrace使用@OnMethod注解定义需要分析的方法入口

 
 

在@OnMethod注解中,需要指定class、method以及location等,class表明需要监控的类,method表明需要监控的方法,指定方式如下:
1、使用全限定名:clazz="com.metty.rpc.common.BtraceCase", method="add"
2、使用正则表达式:clazz="/javax\\.swing\\..*/", method="/.*/"
3、使用接口:clazz="+com.ctrip.demo.Filter", method="doFilter"
4、使用注解:clazz="@javax.jws.WebService", method=""@javax.jws.WebMethod"
5、如果需要分析构造方法,需要指定method="<init>"

@Location

定义Btrace对方法的拦截位置,通过@Location注解指定,默认为Kind.ENTRY
1、Kind.ENTRY:在进入方法时,调用Btrace脚本
2、Kind.RETURN:方法执行完时,调用Btrace脚本,只有把拦截位置定义为Kind.RETURN,才能获取方法的返回结果@Return和执行时间@Duration

 
 

3、Kind.CALL:分析方法中调用其它方法的执行情况,比如在execute方法中,想获取add方法的执行耗时,必须把where设置成Where.AFTER

 
 

4、Kind.LINE:通过设置line,可以监控代码是否执行到指定的位置

 
 

5、Kind.ERROR, Kind.THROW, Kind.CATCH
用于对某些异常情况的跟踪,包括异常抛出,异常被捕获,异常未捕获被抛出方法之外

如何使用Btrace定位问题

1、找出所有耗时超过1ms的过滤器Filter

 
 

由于@Dutation返回的时间是纳秒级别,需要进行转换,如果定位一个Filter性能变慢,接着使用@Location(Kind.CALL)进行更细粒度的分析。

2、分析哪个方法调用了System.gc(),调用栈如何?

 
 

通过查看调用栈,可以很清楚的发现哪个类哪个方法调用了System.gc()

3、统计方法的调用次数,且每隔1分钟打印调用次数

 
 

Btrace的@OnTimer注解可以实现定时执行脚本中的一个方法

4、方法执行时,查看对象的实例属性值

 
 

通过反射机制,可以很方法的得到当前实例的属性值

总结

Btrace能做的事情太多,但使用之前切记检查脚本的可行性,一旦Btrace脚本侵入到系统中,只有通过重启才能恢复。

作者:占小狼
链接:https://www.jianshu.com/p/dbb3a8b5c92f
來源:简书

如何在生产环境使用Btrace进行调试的更多相关文章

  1. .NET C#微信公众号开发远程断点调试(本地远程调试生产环境代码)

    最近在做微信公众号开发,由于之前没有接触过,突然发现调试不方便,不方便进行断点跟踪调试.因为微信那边绑定的服务器地址必须是公网地址,但是还是想进行断点调试(毕竟这样太方便了,程序有Bug,一步步断点跟 ...

  2. web移动端生产环境调试

    如果是开发环境,比较容易: 最笨的方法是手机开QQ电脑开QQ把做好的页面传给手机QQ直接打开.. 参考: http://blog.allenm.me/2014/05/mobile-web-debug- ...

  3. yarn cluster和yarn client模式区别——yarn-cluster适用于生产环境,结果存HDFS;而yarn-client适用于交互和调试,也就是希望快速地看到application的输出

    Yarn-cluster VS Yarn-client 从广义上讲,yarn-cluster适用于生产环境:而yarn-client适用于交互和调试,也就是希望快速地看到application的输出. ...

  4. 如何将生产环境的服务Docker镜像拉取到本地进行调试

    背景 很多时候我们在将开发环境的代码推送到GitLab上面以后,我们在测试的时候发现了问题后无法通过现有的日志输出级别来定位问题,比如我们需要看EFCore生成的SQL语句,在生产环境我们是不可能输出 ...

  5. Vue生产环境调试的方法

    vue 生产环境默认是无法启用vue devtools的,如果生产应用出了问题,就很难解决.. 原理 先说下vue如何判断devtools是否可用的. vue devtools扩展组件会在window ...

  6. ruby on rails 生产环境调试项目日志查看

    1.项目目录:log/production.log 2.nginx日志:/opt/nginx/logs 生产环境下做的任何更改都要重启服务器 重启 sudo kill $(cat /opt/nginx ...

  7. Java生产环境下性能监控与调优详解视频教程 百度云 网盘

    集数合计:9章Java视频教程详情描述:A0193<Java生产环境下性能监控与调优详解视频教程>软件开发只是第一步,上线后的性能监控与调优才是更为重要的一步本课程将为你讲解如何在生产环境 ...

  8. MySQL 系列(四)主从复制、备份恢复方案生产环境实战

    第一篇:MySQL 系列(一) 生产标准线上环境安装配置案例及棘手问题解决 第二篇:MySQL 系列(二) 你不知道的数据库操作 第三篇:MySQL 系列(三)你不知道的 视图.触发器.存储过程.函数 ...

  9. 理解Docker(6):若干企业生产环境中的容器网络方案

    本系列文章将介绍 Docker的相关知识: (1)Docker 安装及基本用法 (2)Docker 镜像 (3)Docker 容器的隔离性 - 使用 Linux namespace 隔离容器的运行环境 ...

随机推荐

  1. 树形插件 --- zTree

    地址:http://www.treejs.cn/v3/api.php

  2. 设置滚动条scrolltop

    scrolltop用来设置页面的滚动条的位置 兼容性:链接 $().scrolltop(值)

  3. main.js 里的/* eslint-disable no-new */

    注意项目中的这个,它的作用是: 在js里面,new 一个对象,需要赋值给某个值(变量),用Vue实例化的时候,不需要赋值给值(变量),所以要单独给配一条规则,给new Vue这行代码上面加这个注释,把 ...

  4. java 对象锁学习

    机制 锁机制是用来解决多线程共享资源时产生的冲突问题的.java 为每一个对象关联一个对象锁,通常把锁分为对象锁和类锁,他们的本质都是对象锁,只不过对象锁关联的是类的 Object 对象 (java. ...

  5. JS定义一个立即执行的可重用函数

    我定义了一个函数表达式 testFun var testFun = (function() { ... //函数内容})(); 测试结果:虽然 testFun 函数有如愿在页面加载后立即被执行,但再次 ...

  6. ie7 下 float换行问题与vertical-align:middle; 失效问题

    声明:web小白的笔记,欢迎大神指点!联系QQ:1522025433. ie7 下 float换行问题 请直接看代码中和代码中的注释: <!doctype html> <html&g ...

  7. VS-常用的快捷键-总结

    1: 快速添加引用 === Shift+Alt+F10; 也可用于实现抽象类 2: 直接添加属性 ===prop+Tab+Tab; 3: 根据字段添加属性 === Ctrl +r+e; 4: 格式化代 ...

  8. Ubuntu 下安装LEMP环境 实战

    ---恢复内容开始--- 1.nginx的服务端的安装 打开命令行终端,在终端输入,sudo apt-get install nginx  回车即开始安装 kxlc-t@ubuntu:~$ sudo ...

  9. 在php中调用以及编写接口(转)

    如: http://localhost/openUser.php?act=get_user_list&type=json 在这里openUser.php相当于一个接口,其中get_user_l ...

  10. js在字符串中提取数字

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...