目录
企业级的应用系统开发大多数会使用Java语言,并且使用Oracle J2
EE架构。Java程序运行在HotSot VM (就是常用的JVM,也包括OpenJDK)之上,通过堆JVM的监控,我们可以度量java程序效率,分析程序的性能问题。
一、jps
我们要知道机器上运行的JVM进程号可以由jps得到。jps命令返回当前系统中的java进程号。
jps命令的参数如下:
-l:返回Java进程全路径。
-q:仅显示进程ID。
-v:返回JVM参数,例如堆大小,此命令方便我们查看JVM大小,不用去找配置文件。
jps[ip]:列出远程机器上的Java进程信息,不过这需要安全授权,在远程机器%JAVA_HOME%/bin/目录存储jstatd.all.policy 文件。
grant codebase "file:${java.home}/../lib/tools.jar"{
permission java.security.AllPermission;}
然后,在远程机器上启动命令进行注册
jstatd -J-Djava.security.policy=jstatd.all.policy
为了方便,我们可以做一个批处理文件jstatd.bat
%JAVA_HOME%\bin\jstatd -J-Djava.security.policy=jstatd.all.policy
远程机器jstatd启动后,也可以使用JVisualvm 在本地机器对远程JVM进行监控。
当机器上有多个JVM进程时,如何确定自己访问的服务对应哪一个java进程?在访问服务器时,URL中会有端口号(默认为80),Linux下可以通过ps命令得知进程号和端口号。
二、jstat
JVM内存不够用,内存溢出通过监控JVMHeap信息进行分析,jstat信息进行分析,jstat可以用来查看JVM堆的统计信息,命令格式如下:
jstat [generaloption | outputoptions vmid [][count]]]interval[s|ms
generaloption 代表选项,常用的选项有以下几个。
class :用于查看类加载情况的统计。
compiler:用于查看HotSpot 中即时编译器情况的统计。
gc:用于查看JVM中堆的垃圾收集情况的统计。
gccapacity:用于查看新生代(young)老年代(old)及持久代(permanent)的存储容量情况。
gccause :最后一次及当前正在发生垃圾收集的原因。
gcnew:用于查看新生代垃圾收集情况。
gcnewcapacity:用于查看新生代的存储容量情况。
gcold:用于查看老年代及持久发生GC的情况。
gcoldcapacity:用于查看老年代的容量。
gcpermcapacity:用于查看持久代的容量。
Printcompilation HotSpot:编译方法的统计。
gcutil:GC统计。
Loaded:加载类的数目。
Bytes:加载类的Size,单位为Byte。
Unloaded:卸载类的数目。
NGC:新生代中当前的容量(单位为Byte)。
S0C:新生代中第一个survivor(幸存区)的容量(单位为 Byte)。
SIC:新生代中第二个survivor(李存区)的容量(单位为 Byte)。
EC:新生代中 Eden(伊甸园)的容量(单位为Byte)
OGCMN:老年代中初始化大小(单位为Byte)。
OGCMX:老年代的最大容量(单位为 Byte)。
OGC:老年代当前大小(单位为 Byte)。
PGCMI:持久代中初始化大小(单位为Byte)
PGCMX:持久代的最大容量(单位为 Byte)。
PGC:持久代当前新生成的容量(单位为 Byte)。
SOU:新生代中第一个survivor(幸存区)目前已使用的空间(单位为Byte)。
SIU:新生代中第二个survivor(幸存区)目前已使用的空间(单位为 Byte)。
EU:新生代中 Eden(伊甸园)目前已使用的空间(单位为Byte)。
OC:老年代的容量(单位为 Byte)。
OU:老年代目前已使用的空间(单位为Byte)。
PC:持久代的容量(单位为 Byte)。
PU:持久代目前已使用的空间(单位为 Byte)。
YGC:JVM 启动到采样时新生代中 gc的次数。
YGCT:JVM 启动到采样时新生代中 gc所用的时间(单位为秒)。
FGC:IVM启动到采样时老年代(Fulgc)gc的次数。
FGCT:IVM启动到采样时老年代(Fulgc)gc所用的时间(单位为秒)。
GCT:JVM 启动到采样时 gc用的总时间(单位为秒)。
三、jstack
jstack 用于生成Java虚拟机当前时刻的线程信息(快照)。快照主要用来了解线程出现长时间停顿的原因,如死锁,死循环,IO等待,请求外部资源导致的长时间等待等。
从快照信息可以知道线程执行到哪个方法,甚至哪一行,帮助我们快速定位程序问题。
jstack命令格式:
jstack [-1] <pid>
如果dump的JVM进程处于Hung的状态,可以添加-F参数。
jstack -F [-m] [-1] <pid>
jstack命令不仅可以dump本机的线程信息,还可以dump远程的JVM中的线程信息。
格式如下:
jstack [-m] [-1] [server_id@]<remote server IP or hostname>
远程使用dump需要配置jstatd。
四、JVM监控的主要指标
垃圾回收(GC)
包括GC的频率、类型(如Young GC, Full GC)、持续时间和暂停时间。频繁的GC活动或长时间的STW(Stop-The-World)事件可能是内存泄漏或其他问题的迹象。
堆内存使用情况
监测堆内不同区域(Eden区、Survivor区、老年代)的内存分配与释放状况,以及整体堆大小的变化趋势。
非堆内存
涉及永久代/元空间(Metaspace)、直接缓冲区等非堆区域的使用量,这些区域如果增长过快也可能导致OOM(OutOfMemoryError)错误。
线程状态
记录当前活跃线程数、阻塞线程数、等待线程数等信息,帮助发现可能存在的死锁或资源竞争问题。
类加载器行为
监视类加载的数量及其占用的空间,有助于了解是否存在不必要的类实例化或类卸载失败的情况。
CPU利用率
评估JVM进程消耗的CPU资源比例,过高或过低都可能是性能瓶颈的表现。
五、图形界面监控工具
JConsole
提供了图形化的JVM监控界面,能够直观地展示JVM的各项性能数据,如内存、线程、类加载等,并且可以通过JMX远程连接到其他机器上的JVM实例进行监控1。
VisualVM
集成了多个JDK工具的功能,不仅限于基本的性能监控,还包括内存泄漏检测、方法级性能剖析等功能,是一个功能强大的一站式解决方案。
Java Mission Control (JMC)
由Oracle开发,专注于生产环境中JVM的性能调优,特别适合用于长期监控和历史数据分析。
Arthas
阿里巴巴开源的一款Java诊断工具,适用于在线环境中快速定位问题。
六、第三方监控工具
Eclipse MAT (Memory Analyzer Tool)
专门针对Java堆内存分析,可以帮助查找内存泄漏的原因。
JProfiler
一款商业级别的性能分析工具,支持CPU、内存、线程等多个维度的深度分析。
Prometheus + JMX Exporter
通过Prometheus抓取JVM暴露出来的JMX指标,再利用Grafana等工具进行可视化展示,非常适合云原生架构下的持续监控。
在性能测试期间,选择适当的JVM监控工具和技术可以极大地提高故障排除效率,同时为优化应用程序性能提供坚实的基础。根据具体的业务场景和技术要求,可以选择不同的工具组合来满足监控需求。例如,在开发阶段可能更倾向于使用简单易用的命令行工具;而在生产环境中,则可能会依赖更为专业和全面的APM平台来进行深入分析。
阅读后若有收获,不吝关注,分享,在看等操作!!!