[转帖]Java调优系列之工具篇之btrace、gperftools

java,系列,工具,btrace,gperftools · 浏览次数 : 0

小编点评

**btrace工具分析Java堆外内存泄露** **主要分析内容:** * gperftools是一个用于分析和排查Java堆外内存泄露的工具。 * gperftools可以从Linux系统上安装,但也需要在64位系统上进行安装。 * gperftools支持在Windows系统上使用。 * gperftools使用Btrace技术收集和分析Java堆外内存泄露的信息。 * Btrace允许用户设置分析参数,包括堆外内存泄露时间和输出格式。 **结果展示:** * 进程使用最多的内存是 Java方法、线程堆栈和native handles。 * Java方法、线程和native handles占用的比例分别为93.9%,9.8%和93.9%。 * 进程创建的heap文件大小为300.2 MB。 * 进程最终释放了17.7 MB的heap空间。 **结论:** 该工具可以有效地识别和分析Java堆外内存泄露问题。通过设置分析参数,用户可以获得详细的分析结果,帮助解决内存泄露问题。

正文

https://github.com/landon30/Bulls/wiki/java-profiling-tools

 

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 = "")
  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原理图解

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 xxx xxx 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/xxx/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
[xxx@zz landon]$ sh nonHeapLeak.sh
$ ll /tmp/*.heap
-rw-rw-r-- 1 xxx xxx 1048562 6月  14 22:45 /tmp/nonheapleak_10821.0001.heap
-rw-rw-r-- 1 xxx xxx 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通讯

与[转帖]Java调优系列之工具篇之btrace、gperftools相似的内容:

[转帖]Java调优系列之工具篇之btrace、gperftools

https://github.com/landon30/Bulls/wiki/java-profiling-tools landon 网络游戏资深服务器架构师 2018-06-14 线上遇到了问题? 服务上线出问题,想增加打印日志怎么办? 线上怀疑某个接口慢,想打印接口耗时怎么办? 线上某个接口报错

[转帖]引人入胜,实战讲解“Java性能调优六大工具”之linux命令行工具

Java性能调优六大工具之Linux命令行工具 为了能准确获得程序的性能信息,需要使用各种辅助工具。本章将着重介绍用于系统性能分析的各种工具。熟练掌握这些工具,对性能瓶颈定位和系统故障排查都很有帮助。 1,Linux命令行工具2, Windows工具3,JDK命令行工具4,JConsole工具5,

[转帖]Java游戏服务器调优实践

https://www.jianshu.com/p/344f8141b63e landon资深网络游戏服务器架构师 系统性能定义 Throughput 吞吐量,也就是每秒钟可以处理的请求数,任务数 Latency 系统延迟,也就是系统在处理一个请求或一个任务时的延迟 二者关系 Throughput越

[转帖]Java游戏服务器调优实践

https://www.jianshu.com/p/344f8141b63e Java Profiling Practice landon资深网络游戏服务器架构师 系统性能定义 Throughput 吞吐量,也就是每秒钟可以处理的请求数,任务数 Latency 系统延迟,也就是系统在处理一个请求或一

[转帖]java性能分析之火焰图

http://t.zoukankan.com/lemon-le-p-13820204.html 原由 最近因为kafka、zookeeper、ES和相关的Java应用的内存问题搞的头大,做运维将近4年,对Java调优、性能方面的知识了解的少之又少,是时候下定决心来对他多一个学习了。不能一口吃成一个胖

[转帖]揭密Java常用性能调优工具的底层实现原理

https://zhuanlan.zhihu.com/p/547081135 本文来自于社区专家鸠摩【《深入剖析Java虚拟机:源码剖析与实例详解》作者】的独家干货,更多文章可去专家主页:鸠摩主页 | HeapDump性能社区 正文: 当Java虚拟机出现故障和性能问题时,我们通常会借助一些业界知名

[转帖]人工智能 Java混合模式火焰图

https://www.dazhuanlan.com/smallnight/topics/1040103 在做性能调优的时候,我们通常会借助一些性能分析工具(比如 perf,DTrace)分析系统资源的使用情况,比如 CPU、内存等,但这些工具分析的结果通常是文本形式,不够直观,不便于快速定位系统瓶

[转帖]人工智能 Java混合模式火焰图

https://www.dazhuanlan.com/smallnight/topics/1040103 在做性能调优的时候,我们通常会借助一些性能分析工具(比如 perf,DTrace)分析系统资源的使用情况,比如 CPU、内存等,但这些工具分析的结果通常是文本形式,不够直观,不便于快速定位系统瓶

[转帖]用实力诠释细节!“Java性能调优六大工具”之JDK命令行工具

https://www.zhihu.com/people/javajia-gou-ji-zhu-44/posts JDK命令行工具 在JDK的开发包中,除了大家熟知的java.exe和javac.exe外,还有一系列辅助工具。这些辅助工具位于JDK安装目录下的bin目录中,可以帮助开发人员很好地解决

[转帖]发布即巅峰!万字长文:Java性能调优六大工具:MAT内存分析工具

jianshu.com/p/4ed3dd8b7b83 MAT是MemoryAnalyzerTool的简称,它是一款功能强大的Java堆内存分析器,可以用于查找内存泄漏以及查看内存消耗情况。MAT是 基于Eclipse开发的一款免费的性能分析工具,读者可以在http://www.eclipse.org