JVM性能调优监控工具

# jdk版本
[root@localhost ~]# java -version
java version "1.8.0_271"
Java(TM) SE Runtime Environment (build 1.8.0_271-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.271-b09, mixed mode)

一、 jps(Java Virtual Machine Process Status Tool):基础工具

jps主要用来输出JVM中运行的进程状态信息。

  • 语法
jps [options] [hostid]
  • 参数
参数说明
-q不输出类名、Jar名和传入main方法的参数
-m输出传入main方法的参数
-l输出main类或Jar的全限名
-v输出传入JVM的参数
  • 示例
[root@localhost ~]# jps -ml
11252 test-jvm.jar
11579 sun.tools.jps.Jps -ml

二、 jstack

jstack主要用来查看某个Java进程内的线程堆栈信息。jstack可以定位到线程堆栈,根据堆栈信息我们可以定位到具体代码,也经常用来排除死锁情况,所以它在JVM性能调优中使用得非常多。

  • 语法
jstack [option] pid
jstack [option] executable core
jstack [option] [server-id@]remote-hostname-or-ip
  • 参数
参数说明
-F当正常输出的请求不被响应时,强制输出线程堆栈
-m如果调用到本地方法的话,可以显示C/C++的堆栈
-l除堆栈外,显示关于锁的附加信息,在发生死锁时可以用jstack -l pid来观察锁持有情况
  • 示例
[root@localhost ~]# jstack 26563
.............省略
"http-nio-8080-exec-1" #13 daemon prio=5 os_prio=0 tid=0x00007f66fca4f800 nid=0x67d1 runnable [0x00007f66d85be000]
   java.lang.Thread.State: RUNNABLE
	at top.dongxibao.demo.controller.TestJvm.testJstack1(TestJvm.java:51)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
.............省略

三、 jmap(Memory Map)和 jhat(Java Heap Analysis Tool)

jmap可以查看堆内存的初始化信息以及堆内存的使用情况,还可以生成dump文件来进行详细分析。然后使用jhat来进行分析

  • 语法
jmap [option] pid
jmap [option] executable core
jmap [option] [server-id@]remote-hostname-or-ip
  • 参数
参数说明
heap显示Java堆详细信息
histo[:live]显示堆中对象的统计信息
clstats打印类加载器信息
finalizerinfo显示在F-Queue队列等待Finalizer线程执行finalizer方法的对象
dump:<dump-options>生成堆转储快照
  • 示例

查看堆栈信息

[root@localhost ~]# jmap -heap 27111
Attaching to process ID 27111, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.271-b09

using thread-local object allocation.
Mark Sweep Compact GC

Heap Configuration:
   MinHeapFreeRatio         = 40
   MaxHeapFreeRatio         = 70
   MaxHeapSize              = 104857600 (100.0MB)
   NewSize                  = 34930688 (33.3125MB)
   MaxNewSize               = 34930688 (33.3125MB)
   OldSize                  = 69926912 (66.6875MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
New Generation (Eden + 1 Survivor Space):
   capacity = 31457280 (30.0MB)
   used     = 16189512 (15.439521789550781MB)
   free     = 15267768 (14.560478210449219MB)
   51.46507263183594% used
Eden Space:
   capacity = 27983872 (26.6875MB)
   used     = 13296472 (12.680503845214844MB)
   free     = 14687400 (14.006996154785156MB)
   47.514768506659834% used
From Space:
   capacity = 3473408 (3.3125MB)
   used     = 2893040 (2.7590179443359375MB)
   free     = 580368 (0.5534820556640625MB)
   83.29110775353773% used
To Space:
   capacity = 3473408 (3.3125MB)
   used     = 0 (0.0MB)
   free     = 3473408 (3.3125MB)
   0.0% used
tenured generation:
   capacity = 69926912 (66.6875MB)
   used     = 9052064 (8.632720947265625MB)
   free     = 60874848 (58.054779052734375MB)
   12.945036097118088% used

11274 interned Strings occupying 938016 bytes.

生成堆转储快照dump文件并使用jhat查看

[root@localhost ~]# jmap -dump:format=b,file=/tmp/dump.dat 27111
Dumping heap to /tmp/dump.dat ...
Heap dump file created
# -J-Xmx512m限定最大内存
[root@localhost ~]# jhat -J-Xmx512m -port 9999 /tmp/dump.dat 
Reading from /tmp/dump.dat...
Dump file created Sat Nov 28 17:41:33 CST 2020
Snapshot read, resolving...
Resolving 194937 objects...
Chasing references, expect 38 dots......................................
Eliminating duplicate references......................................
Snapshot resolved.
Started HTTP server on port 9999
Server is ready.

在这里插入图片描述

四、jstat(JVM统计监测工具)

可以检测Java程序运行的实时情况,包括堆内存信息和垃圾回收信息,我们常常用来查看程序垃圾回收情况。

  • 语法
jstat [ generalOption | outputOptions vmid [interval[s|ms] [count]] ]
  • 常用命令jstat -gc pid信息字段
参数说明
S0C年轻代中 To Survivor 的容量(单位 KB)
S1C年轻代中 From Survivor 的容量(单位 KB)
S0U年轻代中 To Survivor 目前已使用空间(单位 KB)
S1U年轻代中 From Survivor 目前已使用空间(单位 KB)
EC年轻代中 Eden 的容量(单位 KB)
EU年轻代中 Eden 目前已使用空间(单位 KB)
OC老年代的容量(单位 KB)
OU老年代目前已使用空间(单位 KB)
MC元空间的容量(单位 KB)
MU元空间目前已使用空间(单位 KB)
YGC从应用程序启动到采样时年轻代中 gc 次数
YGCT从应用程序启动到采样时年轻代中 gc 所用时间 (s)
FGC从应用程序启动到采样时 老年代(Full Gc)gc 次数
FGCT从应用程序启动到采样时 老年代代(Full Gc)gc 所用时间 (s)
GCT从应用程序启动到采样时 gc 用的总时间 (s)
  • 示例
[root@localhost ~]# jstat -gc 27111
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
3392.0 3392.0  0.0    0.0   27328.0   1047.1   68288.0    11389.2   30080.0 28101.5 3968.0 3585.8     13    0.057   2      0.040    0.097

六、实例

1.内存泄漏

  • Java测试代码
/**
 * 模拟内存泄漏
 */
@GetMapping(value = "/memory/leak")
public String testMemoryLeak() {
    System.out.println("模拟内存泄漏");
    for (int i = 0; i < 5000; i++) {
        ThreadLocal<Byte[]> localVariable = new ThreadLocal<Byte[]>();
        // 为线程添加变量
        localVariable.set(new Byte[4096 * 1024]);
    }
    return "ok";
}
  • 运行项目访问接口
# 用命令行加上堆内存大小限制,同时设置内存溢出的时候输出堆栈快照并输出日志。
[root@localhost ~]# java -jar -Xms100m -Xmx100m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heapdump.hprof -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:/tmp/heaplog.log test-jvm.jar
[root@localhost ~]# curl localhost:8080/memory/leak
  • 报错信息
java.lang.OutOfMemoryError: Java heap space
  • jstat -gc pid 命令来看看程序的GC情况
[root@localhost ~]# jstat -gc 27871
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
3392.0 3392.0  0.0   568.8  27328.0  27328.0   68288.0    55987.3   31232.0 29113.5 4096.0 3708.6     18    0.085   3      0.121    0.206
  • 分析生成的.hprof文件

Windows下使用JDK自带Java Visual VM工具查看

eclipse插件MAT和idea插件jProfiler也可以分析

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2.找出某个Java进程中最耗费CPU的Java线程并定位堆栈信息

  • java测试代码
/**
 * 测试jstack
 */
@GetMapping(value = "/cpu/loop")
public String testCpuLoop() {
    while (true) {
        //Do Nothing
    }
}
  • 运行项目访问接口
[root@localhost ~]# java -jar -Xms100m -Xmx100m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heapdump.hprof -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:/tmp/heaplog.log test-jvm.jar
[root@localhost ~]# curl localhost:8080/cpu/loop
  • 查看进程id
[root@localhost ~]# jps
26563 jar
26589 Jps
  • 根据进程id找到消耗CPU最高的线程
    在这里插入图片描述

  • 将消耗CPU最高的线程转成16进制

[root@localhost ~]# printf "%x" 26577
67d1
  • jstack查找这个线程的信息
# -A 10表示查找到所在行的后10行
[root@localhost ~]# jstack 26563 | grep -A 10 67d1
"http-nio-8080-exec-1" #13 daemon prio=5 os_prio=0 tid=0x00007f66fca4f800 nid=0x67d1 runnable [0x00007f66d85be000]
   java.lang.Thread.State: RUNNABLE
	at top.dongxibao.demo.controller.TestJvm.testJstack1(TestJvm.java:51)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879)

参考文章

https://mp.weixin.qq.com/s/w61tw4qHY2AvJqmp_oZI7A

https://mp.weixin.qq.com/s/fcYbt3wUhcZlBeZy0RfgGQ

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java 允许您玩在线游戏,与世界各地的人聊天,计算您的按揭利息,并以 3D 形式查看图像。这些以 Java 编程语言编写的应用程序和可从浏览中访问的应用程序称为小程序。公司还将 Java 小程序用于内部网应用程序和其他电子商务的解决方案。所有主要行业的公司都在使用 Java。无论是部署在手机、嵌入式设备、游戏机、笔记本电脑还是数据中心,Java 都提供了当今网络应用所需要的丰富的用户界面、性能、多功能性、可移植性和安全性。Java 平台标准版软件是快速开发和部署安全、便携式应用程序的首选平台,可跨大多数操作系统的服务器和桌面系统。 Java 平台标准版(Java SE)可让您在台式机和服务器以及当今苛刻的嵌入式环境中开发和部署 Java 应用程序。Java 提供了当今应用程序所需的丰富的用户界面、性能、通用性、可移植性和安全性。 Java SE Runtime Environment(运行时环境)包含了运行以 Java 编程语言编写的程序所必需的 Java 虚拟机、运行时类库和 Java 应用程序启动器。 Java 平台的安全性 一个由角色提供的安全信息的描述。适用于开发人员,系统管理员,家庭用户和安全专业人士。 主要特点: - 在一个平台上编写软件,并可在几乎任何其它平台上运行 - 创建的程序可在 Web 浏览器和 Web 服务中运行 - 可开发用于在线论坛、商店、投票、HTML 表单处理等服务器端应用程序 - 结合基于 Java 技术的应用程序或服务来创建高度可定制的应用程序或服务 - 为手机、远程处理器、低成本消费产品和几乎任何具有数字内核的设备编写功能强大且高效的应用程序 Java SE 8 现在可用 Java 平台标准版 8(Java SE 8)是一个主要的功能版本。它包含了很多功能领域的新功能和增强功能。Java SE 8 通过减少样板代码,改进了集合和注释,简单的并行编程模型和更有效地利用现代多核处理器,提高了开发人员的工作效率和显着的增强了应用程序的性能。 Java SE 8u172 版本更新:2018年4月17日
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值