使用jcmd进行JVM调整


Java应用程序经常遇到多个性能问题。通常,性能问题是由于JVM调整效率低下所致。我们提供了JDK / JRE附带的许多工具,其中一些可以通过商业途径获得。对于开发人员来说,了解这些JVM调优帮助工具以创建具有最佳性能的应用程序是一件好事。

显然,拥有所有工具的知识是最好的,但是Java jre本身提供了一个工具(从Java7开始),它可以提供有关Java应用程序的重要信息。我说的是jcmd,它使用起来非常简单,并且可以提供各种各样的信息。

什么是jcmd? 按照手册,jcmd是一个实用程序,可将诊断命令请求发送到正在运行的Java虚拟机(即JVM)。

该实用程序从JVM获取各种运行时信息。而且要注意的是,它必须在运行JVM的同一台计算机上使用。

如何使用jcmd 为了解释该工具的用法,让我们在您的计算机上运行一个示例Java应用程序。

运行Web应用程序 我用一个简单的控制器创建了一个简单的Web应用程序(JvmtuningApplication),以返回String消息。

样品请求控制器

1.png 图。1。样品请求控制器 使用一些VM参数运行应用程序:

-Xss256k -Xms512m -Xmx512m -XX:MaxMetaspaceSize = 256m

获取pid 每个进程都有一个关联的进程ID,称为pid。要获得与我们的应用程序关联的pid,可以使用jcmd本身,它将列出所有适用的Java进程。

jcmd获取pid

2.png 图2。jcmd获取pid 在这种情况下,我们的应用程序的pid是2171。

获取可能的jcmd用法列表 jcmd获取可用的命令选项 3.png 图3。jcmd获取可用的命令选项 在这里,您可以使用jcmd命令查看可用选项的数量。

jcmd命令 现在,让我们来看一些有用的选项,以获取有关正在运行的JVM的详细信息。

虚拟机版本

这是为了获得JVM基本详细信息

获取基本的JVM详细信息

4.png 图4。jcmd命令-VM.version

虚拟机标志 这将打印我们的应用程序使用的所有VM参数,这些参数可以由我们指定,也可以由jvm设置为默认值。在这里可以注意到各种默认的VM参数。

jcmd命令-VM.flags

5.png 图5。jcmd命令-VM.flags 其他命令,例如VM.system_properties,VM.command_line,VM.uptime,VM.dynlibs,还提供了有关所使用的各种其他属性的其他基本和有用的详细信息。

线程打印

该命令用于获取线程转储,即它将打印当前正在运行的所有线程的堆栈跟踪。以下是使用它的方法,根据运行的线程数,它可以提供较长的输出。

jcmd命令-线程。 打印

6.png 图6。jcmd命令-线程。打印

GC.class_histogram 该命令将提供有关堆使用情况的重要信息,并列出所有类(外部类或特定于应用程序的类)以及许多实例,并按堆使用情况对它们的堆使用情况进行排序。由于此列表很长,因此可以使用grep命令来查找其已知的类以验证详细信息,或者可以将此命令的输出路由到文件输出。

jcmd命令-GC.class_histogram

图7。jcmd命令-GC.class_histogram7.png

Grep用法 使用grep的jcmd命令 8.png 图8。使用grep的jcmd命令 GC.heap_dump

如果要立即获取jvm堆转储,则可以执行此命令。以下是命令用法,其中jvmTuningHeapDum是文件名。

请注意,最好提供完整的文件路径,而不是仅提供文件名。否则,它将在某个随机位置创建一个文件,尽管可以使用“ find -name jvmTuningHeapDum ”或任何其他此类工具在系统中找到该文件。

jcmd命令-GC.heap_dump

9.png 图9。jcmd命令-GC.heap_dump JFR命令选项

如果要分析其应用程序的性能问题,那么JFR(即Java Flight Recorder)是一种提供信息的实用工具。尽管JFR是一项商业功能,但人们可以在其本地计算机上免费使用它。

jcmd命令可以提供相关的JFR文件以进行动态分析。默认情况下,JFR功能处于禁用状态,要启用这些功能,可以选择以下方式:

jcmd命令-JFR.start

10.png 图10。jcmd命令-JFR.start

jcmd命令解锁商业功能

11.png 图11。jcmd命令解锁商业功能

启用JFR功能后,开始JFR录制。就我而言,我要求在延迟10秒后记录30秒。这些可以根据用途进行配置。也可以使用 JFR.check 命令检查记录的状态。

jcmd命令-JFR.start示例用法

12.png 图12。jcmd命令-JFR.start示例用法

记录的JFR文件可在其他实用程序(如JMC)中使用,以进行进一步分析。

VM.native_memory(Native Memory Tracking)

这是最好的命令之一,可以提供有关堆和非堆 内存的许多有用的详细信息。这可用于调整内存使用情况并检测任何内存泄漏。

众所周知,JVM内存使用取决于许多内存区域,大致分为堆和非堆内存。要获取完整的JVM内存使用情况的详细信息,请使用此实用程序。如果要创建分布式应用程序,这对于定义应用程序容器的大小很有用,如果正确调整,则可以节省成本。

要使用此功能,我必须使用其他参数重新启动应用程序,即-XX:NativeMemoryTracking = summary 或 -XX:NativeMemoryTracking = detail。

检查是否添加了新的PID和新的VM标志:

jcmd命令获取新的pid

13.png 图13。jcmd命令获取新的pid

jcmd命令获取更新的VM标志

14.png 图14。jcmd命令获取更新的VM标志

运行VM.native_memory 命令将提供如下详细信息:

jcmd命令-VM.native_memory

15.png 图15。jcmd命令-VM.native_memory

除了Java Heap内存外,Thread指定线程正在使用的内存,Class还指定捕获的用于存储类元数据的内存,Code提供用于存储JIT生成的代码的内存,Compiler本身具有一定的空间使用率,类似地,GC占用空间。所有这些都属于本机内存使用情况。

保留的总数可以粗略估计您的应用程序所需的内存,但是各种VM参数仍然可以控制事物,这主要是默认内存使用情况,因为我们尚未配置所有标志。需求分析后可以调整所有内存。

请参阅此处的所有VM参数。

请注意,所有已提交的使用情况均显示实际使用的内存,而保留的则显示jvm预期的使用时间。例如

Java Heap (reserved=524288KB, committed=524288KB)
                (mmap: reserved=524288KB, committed=524288KB)

我们指定了堆内存,即Xms = 512m,相当于524288KB,因此提交的内存与Xms相同。同样,Xmx映射到保留的内存。

此命令提供当前内存使用情况的快照。要分析内存泄漏,应在使用命令启动应用程序后将内存统计信息作为基线

jcmd命令-VM.native_memory基线

16.png 图16。jcmd命令-VM.native_memory基线

然后,可以使用diff来观察更改,确切地使用了内存。随着时间的流逝,随着GC的运行,您会注意到内存的增加和减少。但是,如果仅增加内存使用量,则可能是内存泄漏问题。确定泄漏区域,例如堆,线程,代码,类等。如果您的应用程序需要更多内存,请相应地调整相应的VM参数。

如果内存泄漏在堆中,请进行堆转储(如前所述),或者如果线程数在增加,请使用线程池。如果任何线程导致OOM,则可以调整Xss。

在下面的快照中,可以观察到不同部分的内存增加。

jcmd命令-VM.native_memory差异

17.png

Note:

xxxxxxxxxx

 Thread (reserved=11895KB +529KB, committed=11895KB +529KB)
                (thread #20 +2)
                (stack: reserved=11812KB +520KB, committed=11812KB +520KB)
                (malloc=61KB +7KB #101 +10)
                (arena=22KB +2 #35 +4)

“ stack ”显示线程堆栈内存,这可能与运行应用程序时使用Xss配置的内容不匹配。由于某些jvm系统线程会根据使用情况分配堆栈内存,因此用户无法使用Xss覆盖堆栈内存。

我们将线程堆栈大小指定为Xss = 256k,这里共有18 + 2 = 20个线程。这两个额外的线程是用于处理请求的特定于应用程序的线程,因此为2 *(Xss = 256k)〜520k。


原文链接:http://codingdict.com