压测工具。可对特定接口进行压测,分析tps、响应时间、CPU、内存等性能指标。
jdk 自带可视化工具,可监控CPU、内存、线程等状况。路径: /Library/Java/JavaVirtualMachines/jdk1.8.0_77.jdk/Contents/Home/bin/
jmx (Java Management Extensions)
配置:
-Djava.rmi.server.hostname=xxx
-Dcom.sun.management.jmxremote.port=xxx
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
包括 jmx
监控、dump
文件分析等功能
连接方式和 JConsole
类似,包括CPU、内存、线程等的监控,以及手动执行GC、生成堆dump文件、线程dump文件等功能
CPU、内存等监控:
线程监控:
抽样器:可选择CPU或内存抽样
包括系统概要、堆中的类(以及对应的实例)分析、线程分析、OQL查询等内容
打开 dump 文件:
筛选类:
查看实例对象:
也可直接查看垃圾回收根节点:
官网:https://github.com/gperftools/gperftools/wiki
google 提供的性能分析工具,包括对应用程序CPU、内存等的性能分析。本次主要介绍 heapprofile
工具分析堆外内存。
heapprofile
工具:监控所有的内存分配和释放,内存分配包括: malloc, calloc, realloc, or, new
。底层实现了 malloc
等方法,监控 malloc
等方法的调用。
sudo yum -y install gcc make
sudo yum -y install gcc gcc-c++
wget http://download.savannah.gnu.org/releases/libunwind/libunwind-0.99-beta.tar.gz
./configure --prefix=/tmp/google-perftools/local/libunwind
make
make install
wget https://github.com/gperftools/gperftools/releases/download/gperftools-2.5/gperftools-2.5.tar.gz
./configure --prefix=/tmp/google-perftools/local/gperftools-2.5/
make
make install
vi /etc/ld.so.conf.d/usr_local_lib.conf
添加: /tmp/google-perftools/local/libunwind/lib
export LD_PRELOAD=/tmp/google-perftools/local/gperftools-2.5/lib/libtcmalloc.so
export HEAPPROFILE=/tmp/google-perftools/local/profile/gzip
/tmp/google-perftools/local/gperftools-2.5/bin/pprof --text /usr/local/java/bin/java gzip_7933.0079.heap > text_7933.0079.heap
/tmp/google-perftools/local/gperftools-2.5/bin/pprof --pdf /usr/local/java/bin/java gzip_16205.0093.heap > pdf_16205.0093.heap
含义:
第一列: 使用的直接内存大小
第二列: 第一列所占百分比
第三列: 第二列总和
第四列: 程序和调用者使用的内存大小
第五列: 第四列所占百分比
eclipse 出的内存分析工具。下载地址: http://www.eclipse.org/mat/downloads.php
注:此处只做简单介绍,更多功能请自行挖掘。
如查看 java.nio.Bits
对象,分配了3.4G左右堆外内存:
实例:根据 GCRoot.type
属性查询不可达对象
根据文档显示,GCRoot.Type = 2048
为不可达对象类型,因此 OQL
语句如下:
SELECT s, s.key.toString(), s.@GCRootInfo[0].type FROM com.google.common.cache.LocalCache$StrongAccessWriteEntry s WHERE (s.@GCRootInfo[0].type = 2048)
sun推出的一款针对 java 的动态、安全的追踪工具。官网地址:https://github.com/btraceio/btrace/wiki
注:该工具使用不当可能导致JVM崩溃,线上脚本需验证后再用;且脚本一旦运行,只有重启应用或 kill 进程才能停止。
在运行的 java 程序中动态(字节码)的插入追踪代码,并对追踪的程序进行热交换。可查看某个方法入参、调用堆栈、响应时间、内存信息等,还有一些限制,如不能创建对象、抛异常等。下载的 btrace 包里有实例,路径: /btrace/samples
btrace 注解类型: https://github.com/btraceio/btrace/wiki/BTrace-Annotations
@OnMethod
监控调用了 java.nio.ByteBuffer
类的 allocateDirect()
方法,@Location(Kind.ENTRY)
含义: 在进入 allocateDirect()
方法时执行 traceExecute()
逻辑。
代码: trace_direct_memory.java
import com.sun.btrace.BTraceUtils;
import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.println;
/**
* btrace 追踪直接内存
*
* @author wengliemiao
*/
@BTrace
public class trace_direct_memory {
@OnMethod(
clazz = "java.nio.ByteBuffer",
method = "allocateDirect",
location = @Location(Kind.ENTRY)
)
public static void traceExecute(int capacity) {
println("========================= invoke java.nio.ByteBuffer.allocateDirect(). =========================");
println("param: " + capacity);
BTraceUtils.jstack();
println("Heap:");
println(BTraceUtils.Sys.Memory.heapUsage());
println("Non-Heap:");
println(BTraceUtils.Sys.Memory.nonHeapUsage());
}
}
运行脚本: btrace.sh
#!/bin/bash
export BTRACE_HOME=/home/admin/tmp/btrace
export PATH=$BTRACE_HOME/bin:$PATH
btrace trace_direct_memory.java > result.txt
#dubbo服务可使用如下命令获取 pid
#pid = "$(jps -v | grep "order"|cut -d " " -f1)"
#btrace $pid $currentDir/scripts/trace_direct_memory.java > result.txt
执行命令:
$ ./btrace.sh
注:如果执行脚本时出现: Invalid path 13609 specified: 2/No such file or directory
则说明可能有多个 btrace
命令,此时可以指定 btrace
路径。
运行结果:
========================= invoke java.nio.ByteBuffer.allocateDirect(). =========================
param: 1024
java.nio.ByteBuffer.allocateDirect(ByteBuffer.java)
org.jboss.netty.channel.socket.nio.SocketReceiveBufferPool.acquire(SocketReceiveBufferPool.java:61)
org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:319)
org.jboss.netty.channel.socket.nio.NioWorker.processSelectedKeys(NioWorker.java:280)
org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:200)
org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:44)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
java.lang.Thread.run(Thread.java:748)
Heap:
init = 1073741824(1048576K) used = 144381584(140997K) committed = 1038876672(1014528K) max = 1038876672(1014528K)
Non-Heap:
init = 2555904(2496K) used = 90639560(88515K) committed = 119865344(117056K) max = 1862270976(1818624K)
gdb
可结合 top、pmap
等工具查看进程内存块的内容。
注:该工具会导致应用程序挂起,线上慎用。
/proc/${pid}/
目录下 smaps
等文件查看内存占用相关信息