Java调优系列之工具篇之btrace、gperftools

Java调优系列之工具篇之btrace、gperftools

landon 网络游戏资深服务器架构师
2018-06-14

线上遇到了问题?

  1. 服务上线出问题,想增加打印日志怎么办?
  2. 线上怀疑某个接口慢,想打印接口耗时怎么办?
  3. 线上某个接口报错,想看看调用的参数和谁调用了怎么办?
  4. 线上出错了,想看某个对象的数据怎么办?
  5. 线上出错了,想看一下jvm的一些信息怎么办?
  6. 不确定线上某一行代码执行了怎么办?
  7. ......

传统解决方案

  • 修改源代码 -> 增加相关打印日志 -> hotswap
  • Thread.dumpStack
  • beanshell可以查看内存数据
  • jvm信息可以通过jvm内置命令去获取
  • 缺点
    • 代码侵入式
    • 不灵活
    • 源代码冗余
    • 如果你的服务不支持hotswap呢?

什么是btrace

  • BTrace is a safe, dynamic tracing tool for the Java platform.
  • BTrace can be used to dynamically trace a running Java program (similar to DTrace for OpenSolaris applications and OS). BTrace dynamically instruments the classes of the target application to inject tracing code ("bytecode tracing").
  • 江南白衣
    • Btrace是神器,每一个需要每天解决线上问题,但完全不用Btrace的工程师,都是可疑的

btrace基础

  1. https://github.com/btraceio/btrace
    • 以前sun开源的项目
  2. 下载
    • bin 加入环境变量
    • build 实现包和依赖包
    • samples 示例脚本
    • docs 帮助文档
  3. 基础使用
    • IDE下编写btrace脚本
    • jps找到运行的java进程pid
    • btrace pid btracescript

btrace脚本编写基础事项

  1. IDE编写要引入依赖jar
    • btrace-agent.jar
    • btrace-boot.jar
    • btrace-client.jar
  2. 脚本就是一个.java源文件
  3. @BTrace注解
  4. trace的class要用full name
  5. 只能使用btrace提供的方法,不能自己随意调用(保证性能不受影响,trace才更放心)

btrace实战

  1. 一个简单的偏游戏业务的sample
  2. btrace
    • Locate 定位trace的方法
    • Intercept 对定位到的方法进行拦截
    • Print 打印需要的数据
  3. 典型场景
    • 找出最耗时的业务方法
    • 打印调用堆栈
    • ......

btrace#locate

  1. TraceLocate.java
  2. 举例
    • @OnMethod(clazz = "/practice./", method = "/./")
    • @OnMethod(clazz = "+practice.IHandler", method = "/.*/")
    • @OnMethod(clazz = "/practice.*/", method = "@practice.LogicMethod")
    • @OnMethod(clazz = "/practice.*/", method = "<init>")
  3. 看示例代码

btrace#intercept

  1. TraceIntercept.java
  2. 举例
    • @OnMethod(clazz = "practice.LoginHandler", method = "login", location = @Location(Kind.ENTRY))
    • @OnMethod(clazz = "practice.LoginHandler", method = "login", location = @Location(Kind.RETURN))
    • @OnMethod(clazz = "+practice.IHandler", method = "/.*/", location = @Location(Kind.THROW))
    • @OnMethod(clazz = "practice.LoginHandler", method = "login", location = @Location(value = Kind.CALL, clazz = "/./", method = "/./", where = Where.AFTER))
    • @OnMethod(clazz = "practice.HeroHandler", method = "starUp", location = @Location(value = Kind.LINE, line = 16))
  3. 看示例代码

btrace#print

  1. TracePrint.java
  2. 举例
    • printMethodSignature
    • AnyType
    • Field field = BTraceUtils.field("practice.PlayerService", "playerMap")
    • @TLS thread local share
  3. 看示例代码

btrace#TypicalScenes

  1. TraceTypicalScenes.java
  2. 举例
    • @Duration long duration
      • 纳秒
      • Kind.RETURN
    • BTraceUtils.jstack
    • OnTimer
    • jvm
      • jinfo/jmap/...
      • sizeof/deadlock
  3. 示例代码和自带sample

btrace原理

  1. Client(Java compile api + attach api) + Agent(脚本解析引擎 + ASM + JDK6 Instumentation) + Socket
  2. java attach api附加agent.jar + 脚本解析引擎+asm来重写指定类的字节码 + instrument实现对原有类的替换
  3. 通过JVM Attach API,btrace把自己绑进了被监控的进程 -> 按照脚本定义 -> AOP代码植入

btrace原理图解

image

btrace注意的问题

  1. 限制
    • 为了保证性能不受影响,Btrace不允许调用任何实例方法,必须使用btrace提供的api
  2. BTrace植入过的代码,会一直在
  3. 属于“事后工具” ,即服务已经上线了,无法再通过打印日志等方式埋点分析
  4. 无法trace native
  5. 一定要用IDE写btrace脚本
  6. 其他
    • 有一些脚本细节需要自行体会 如追踪异常的上下文
    • 可以远程、可用于线上生成环境 还有许多其他命令参数如指定文件输出

其他工具和参考

  1. 其他类似工具(可能更强大 但是我个人还是偏向sun的btrace)
  2. 参考

gperftools

  1. 场景
    • 主要分析Java的堆外内存泄露
  2. Java进程占用内存
    • Note that the JVM uses more memory than just the heap. For example Java methods, thread stacks and native handles are allocated in memory separate from the heap, as well as JVM internal data structures
  3. 堆外内存
    • jni
    • nio direct buffer

gperftools#install

  1. 下载地址
  2. install
    • Perftools was developed and tested on x86 Linux systems, and it works in its full generality only on those systems. However, we've successfully ported much of the tcmalloc library to FreeBSD, Solaris x86, and Darwin (Mac OS X) x86 and ppc; and we've ported the basic functionality in tcmalloc_minimal to Windows. See INSTALL for details.See README_windows.txt for details on the Windows port.
    • 强烈建议直接在linux安装,mac文档少,windows不考虑
  3. linux注意问题

堆外内存泄露sample

  1. NonHeapLeakExample.java
    • java.util.zip.Deflater
  2. javac -> jar -> run.sh
    • javac NonHeapLeakExample.java
    • jar cvf NonHeapLeak.jar NonHeapLeakExample.class
    • java -cp ./NonHeapLeak.jar NonHeapLeakExample
  3. top/jmap/jstat
  4. 示例代码和脚本

gperftools排查

  1. java启动脚本增加参数
    • export LD_PRELOAD=/usr/local/lib/libtcmalloc.so
    • export HEAPPROFILE=/tmp/nonheapleak
  2. 启动输出
    • Starting tracking the heap
  3. 查看heap是否生成
    • $ ll /tmp | grep .heap
    • -rw-rw-r-- 1 playcrab playcrab 1048574 Jun 13 16:24 nonheapleak_28759.0001.heap
  4. 分析heap
    • pprof --text $JAVA_HOME/bin/java /tmp/nonheapleak_28759.0001.heap

gperftools结果展示

  1. 结果展示
Using local file /data/home/user00/playcrab/usr/jdk/bin/java.
Using local file /tmp/nonheapleak_28759.0003.heap.
Total: 300.2 MB
   281.9  93.9%  93.9%    281.9  93.9% deflateInit2_
    17.7   5.9%  99.8%     17.7   5.9% os::malloc@907360
     0.3   0.1%  99.9%      0.3   0.1% readCEN
     0.1   0.0% 100.0%    282.0  94.0% Java_java_util_zip_Deflater_init
......
  1. 分析
    • Java_java_util_zip_Deflater_init是一个jni方法 对应java方法
    • 可以看到这块占用内存占用很大

如何找到谁调用了Deflater?

  1. btrace派上用场
@OnMethod(clazz = "java.util.zip.Deflater", method = "<init>")
     public static void traceStack() {
         BTraceUtils.jstack();
     }
  1. 有了Java的调用堆栈,就好办了
  2. 原因
    • deflater没有调用end
    • deflater的底层实现全部是调用jni
    • 只申请了内存但是没有释放

源代码

  1. btrace-sample
  2. NonHeapLeak-sample

Q & A

  • 演示过程中,貌似gperftools的heap没生成,进程kill的时候生成了
    • 可以生成 不过得等一下
    • 从输出看 是差不多6分钟左右 heap文件才生成
$ date
2018年 06月 14日 星期四 22:39:43 CST
[playcrab@achilles landon]$ sh nonHeapLeak.sh
$ ll /tmp/*.heap
-rw-rw-r-- 1 playcrab playcrab 1048562 6月  14 22:45 /tmp/nonheapleak_10821.0001.heap
-rw-rw-r-- 1 playcrab playcrab 1048563 6月  14 22:51 /tmp/nonheapleak_10821.0002.heap

  • 关于btrace的注入问题
1. btrace注入的代码确实一直都在
2. 没有办法移除 因为再次写脚本也是在注入后的基础上
3. 通常来说线上排查问题 我们不会写如定位线上所有的业务方法都进行拦截 肯定会有选择性的 另外和源代码增加日志一样 不会有什么性能问题
4. btraceutils.println是直接发送到了attach的agent的buff(socket)没什么问题,client退出了就不会发了,只不过代码还依然执行而已 landon-本质还是socket通讯
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,755评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,369评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,799评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,910评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,096评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,159评论 3 411
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,917评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,360评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,673评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,814评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,509评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,156评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,123评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,641评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,728评论 2 351

推荐阅读更多精彩内容

  • 一,apk以进程的形式运行,进程的创建是由zygote。 参考文章《深入理解Dalvik虚拟机- Android应...
    Kevin_Junbaozi阅读 2,833评论 0 12
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,638评论 18 139
  • 简介 BTrace是一个安全的JVM动态追踪工具,最初为原Sun公司Kenai项目下面的一个子项目。 典型的使用场...
    lfckop阅读 5,612评论 10 13
  • 为什么要有Btrace? 生产环境系统发生问题时,定位问题需要获取系统运行时的相关数据,如方法参数、返回值、全局变...
    jerrik阅读 881评论 0 2
  • 心里放不下,昨晚看了一夜同学们的日志,白天整个人恍恍惚惚的。矛盾,焦虑充斥了我整个人,告诉自己,都已经退群了,放弃...
    卜芳阅读 139评论 1 1