JVM性能测试实践回忆总结

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/singgel/article/details/89399232

内容的出处来自于我球的一位同事的总结,很全易懂,如果你喜欢开源社区且是contributor欢迎砸你的简历过来[email protected]


目录

 

一、jstat查看jvm的统计信息

1、类加载信息

2、垃圾回收信息(动态的看到垃圾回收信息)

3、JIT编译信息

二、jmap+MAT抓取jvm内存快照(内存溢出、内存泄漏)

1、设置堆的最大内存 最小内存

2、设置非堆的内存大小

3、导出内存映像文件

三、jstack抓取JVM所有的线程Thread dump快照与分析(CPU负载高和死循环/死锁问题分析)

1、jstack抓取所有线程dump快照并分析

2、线程状态

3、CPU负载飙高问题

4、线程死锁问题

四、JVisualVM可视化监控

1、使用JVisualVM进行可视化监控与分析

2、监控本地/远程Tomcat

3、监控远程的普通java进程

五、BTrace排查问题

1、BTrace介绍

2、使用场景

3、使用限制

4、如何定位

5、拦截时机

6、BTrace运行方式

7、BTrace应用

六、Arthas排查问题

1、简介

2、Arthas安装

3、实践


一、jstat查看jvm的统计信息

1、类加载信息

jstat -class 3176 1000 10 //PID 每隔1s钟输出 一共输出10次

2、垃圾回收信息(动态的看到垃圾回收信息)

-gc、-gcutil、 -gccause、 -gcnew、-gcold
jstat -gc 16892 1000 3

S0C、S0U、S1C、S1U:S0和S1的总量与使用量
EC、EU:Eden区总量与使用量
OC、OU:Old区总量与使用量
MC、MU:Metaspace区总量与使用量
CCSC、CCSU:压缩类(启用class文件的短指针32位的)空间总量与使用量
YGC、YGCT:YoungGC的次数与时间
GCT:总的GC时间

3、JIT编译信息

把项目代码编译成native本地代码,存放在Metaspace空间内。
jstat -compiler 16892

编译了3183个方法,有一个getResource方法编译失败

二、jmap+MAT抓取jvm内存快照(内存溢出、内存泄漏)

1、设置堆的最大内存 最小内存

-Xmx32M -Xms32M

2、设置非堆的内存大小

-XX:MetaspaceSize=32M -XX:MaxMetaspaceSize=32M


3、导出内存映像文件

1)内存溢出自动导出

-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=./

2)使用jmap手动导出

jmap -dump:format=b,file=noheap.hprof 2468


3)使用MAT打开并分析dump文件(可以打开分析的有MAT,VisualVM,jprofiler等)

看到底谁在引用这个User对象呢,针对这个对象右键Merge Shortest Paths to GC Roots->exclude all phantom/weak/soft etc.references

查看对象占的字节数,同理对大对象也可右键查看其引用,右键Merge Shortest Paths to GC Roots->exclude all phantom/weak/soft etc.references

三、jstack抓取JVM所有的线程Thread dump快照与分析(CPU负载高和死循环/死锁问题分析)

1、jstack抓取所有线程dump快照并分析

  jstack 29228 >MonitorTuningApplication.txt

2、线程状态


NEW 线程还未启动
RUNNABLE 在JVM中运行状态
BLOCKED 表示在等待锁释放资源(synchronized,ReentrantLock),monitor lock acquired
WAITING 等待另一个线程做一个操作(t.wait(),t.join(),t.notify(),Thread.sleep()等)
TIMED_WAITING 限时等待(t.wait(),t.join(),t.notify(),Thread.sleep()等)
TERMINATED 线程结束


3、CPU负载飙高问题


1)首先项目打包

mvn clean package -Dmaven.test.skip


2)上传服务器并运行

3)top一下看下负载

4)jstack抓取线程快照

jstack 6961 >6961.txt 然后传出来分析

5)进制转换

十进制转16进制

6)定位问题

然后打开导出来的6961.txt文件,搜索1b41,就可以定位到各个线程,然后定位到线程中CPU负载高运行的方法

4、线程死锁问题

top看负载

jstack 7564 >7564.txt,dump文件出来

看运行改PID的所有线程信息,top -p 7564 -H

10进制转16进制,然后打开线程dump文件进行搜索定位

如果发生死锁问题,直接拉到最后,看到dump分析

四、JVisualVM可视化监控

1、使用JVisualVM进行可视化监控与分析

监视是监控JVM内存的(堆内存和Metaspace内存),提供实时堆dump

除了用JVisualVM实时dump外,我们还可以自己导入dump分析

线程是监控该PID下所有的线程,提供实时dump线程信息

对CPU实时抽样,精确定位到每个方法的执行时间和CPU使用情况

Visual GC插件安装

工具->插件->设置->编辑→url换成适合自己JDK版本的url

2、监控本地/远程Tomcat

JVisualVM监控远程的Java进程,例如Tomcat
1、实时监控远程tomcat
修改Catalina.sh
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9004 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.net.preferlPv4Stack=true -Djava.rmi.server.hostname=192.168.115.129"
重启tomcat,./catalina.sh start

远程->右键ip->添加JMX连接->添加9004端口号→确定

进来之后,也是同样的东西

3、监控远程的普通java进程


添加项目启动参数(最重要的是端口号和主机名)
nohup java -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9005 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.net.preferlPv4Stack=true -Djava.rmi.server.hostname=192.168.115.129 -jar monitor_tuning-0.0.1-SNAPSHOT.jar &

远程->右键ip->添加JMX连接->添加9005端口号→确定

也可以实时dump堆快照

实时抽样

五、BTrace排查问题

1、BTrace介绍

Btrace动态地追踪正在运行的java程序(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可以动态的向目标程序的字节码注入追踪代码(Instrumentation+ASM)

2、使用场景

1、接口性能变慢,分析每个方法的耗时情况;
2、 查看方法参数或对象属性
3、查看某一个方法的响应时间
4、查看某一个方法中所有外部调用的响应时间,方便定位方法响应慢的具体位置及原因
5、当在Map中插入大量数据,分析其扩容情况;
6、 查看哪些方法调用了 System.gc() ,调用栈是怎样的
7、 哪些方法发生了异常;

为了更好解决问题,最好还要配合事前准备和进行中监控,事前准备就是埋点嘛,在一些可能出现问题的方法中进行日志输出,进行中监控就是利用一些实时监控工具,例如 VisualVM 、jmc 这些带界面的工具或者 jdk 提供的命令行工具等

3、使用限制

为了保证trace语句只读,最小化对被检测程序造成影响, BTrace对trace脚本有一些限制(比如不能改变被trace代码中的状态) 

  • BTrace class不能新建类, 新建数组, 抛异常, 捕获异常,
  • 不能调用实例方法以及静态方法(com.sun.btrace.BTraceUtils除外)
  • 不能将目标程序和对象赋值给BTrace的实例和静态field
  • 不能定义外部, 内部, 匿名, 本地类
  • 不能有同步块和方法
  • 不能有循环
  • 不能实现接口, 不能扩展类
  • 不能使用assert语句, 不能使用class字面值

4、如何定位


1. 精准定位

直接定位到一个类下的一个方法,上面测试用的例子就是

2. 正则表达式定位

正则表达式在两个"/" 之间,例如下面的例子,监控 controller 包下的所有方法,注意正式环境中,范围尽可能小一点,太大了性能会有影响。
@OnMethod(clazz="/com\\.xueqiu\\.monitor_tuning.controller\\..*/", method="/.*/") public static void anyRead( @ProbeClassName String probeClass, @ProbeMethodName String probeMethod) { BTraceUtils.println(pcn+","+pmn); }
通过在拦截函数的定义里注入@ProbeClassName String probeClass, @ProbeMethodName String probeMethod 参数,告诉脚本实际匹配到的类和方法名。

3. 按接口或继承类定位

例如要匹配继承或实现了 com.kite.base 的接口或基类的,只要在类前加上 + 号就可以了,例如
@OnMethod(clazz="+com.kite.base", method="doSome")

4. 按注解定位

在前面加上 @ 即可,例如@OnMethod(clazz="@javax.jws.WebService", method="@javax.jws.WebMethod") 

5、拦截时机

拦截时机由 location 决定,当然也可为同一个定位加入多个拦截时机,即可以在进入方法时拦截、方法返回时拦截、抛出异常时拦截

1. Kind.Entry与Kind.Return

分别表示函数的开始和返回,不写 location 的情况下,默认为 Kind.Entry,仅获取参数值,可以用 Kind.Entry ,要获取返回值或执行时间就要用 Kind.Return

2. Kind.Error, Kind.Throw和 Kind.Catch

表示异常被 throw 、异常被捕获还有异常发生但是没有被捕获的情况,在拦截函数的参数定义里注入一个Throwable的参数,代表异常

3. Kind.Call 和 Kind.Line  

Kind.Call 表示被监控的方法调用了哪些其他方法,例如:

Kind.Line 监测类是否执行到了设置的行数,例如:

6、BTrace运行方式

两种运行btrace脚本的方式:
1、使用命令行btrace pid btrace_script
2、在JVisualVM中添加Btrace插件,添加classpath

7、BTrace应用

1)拦截指定类和指定方法的参数:

在JVisualVM中运行Btrace:
先下载BTrace Workbench插件

2、右键项目进程pid->Trace application

2)打印耗时超过100ms的方法

3)查看谁调用了GC

六、Arthas排查问题

1、简介

Arthas 是阿里巴巴开源出来的一款线上项目诊断利器,它主要是针对线上环境,能够快速定位问题。

总结一下:VisualVM和Arthas可以相辅相成,前者更像一个全局监测官,监控整体运作情况;而后者更像一个局部调试官,可监测方法,甚至可细化到方法执行前后的参数等,所以它更常用于调试排查

2、Arthas安装

1、使用arthas-boot安装
下载arthas-boot.jar,然后用java -jar的方式启动:
wget https://alibaba.github.io/arthas/arthas-boot.jar
java -jar arthas-boot.jar
打印帮助信息:
java -jar arthas-boot.jar -h
如果下载速度比较慢,可以使用aliyun的镜像:
java -jar arthas-boot.jar --repo-mirror aliyun --use-http


2、使用as.sh安装
Arthas 支持在 Linux/Unix/Mac 等平台上一键安装,请复制以下内容,并粘贴到命令行中,敲 回车 执行即可:
curl -L https://alibaba.github.io/arthas/install.sh | sh
上述命令会下载启动脚本文件 as.sh 到当前目录,你可以放在任何地方或将其加入到 $PATH 中。
直接在shell下面执行./as.sh,就会进入交互界面。
也可以执行./as.sh -h来获取更多参数信息。


3、Windows安装

  1. 点击 这里下载最新的Arthas zip包
  2. 解压缩zip包.
  3. 进入bin目录
  4. 执行以下命令 as.bat $PID

3、实践

1、Dashboard

然后进入dashboard

一目了然的了解系统的状态,哪些线程比较占cpu?他们到底在做什么?


2、查看前3个最耗CPU的线程信息

3、定位到具体的类和方法之后,然后反编译该类,查看代码

4、查找JVM中已经加载的类

5、trace 观察方法执行的调用链和执行时间:

6、watch拦截返回值

7、redefine加载外部的.class文件,redefine jvm已加载的类。
修改完代码后,javac编译,然后redefine加载进来
命令:redefine -p 路径

猜你喜欢

转载自blog.csdn.net/singgel/article/details/89399232