当监视正在运行的Java应用程序时,JConsole是一个很好的工具。 但是,当无法使用JConsole直接连接到JVM(例如,由于网络限制)并且无法进行SSH隧道传输时,那么拥有命令行版本的JConsole会很棒。
jcmx是JConsole的命令行版本。 下载单个jar文件cjmx_2.10-2.1.0-app.jar
,可以通过将tools.jar包含到类路径中来启动它:
java -cp $JAVA_HOME/lib/tools.jar:cjmx_2.10-2.1.0-app.jar cjmx.Main
这将使用以下基本命令打开“ JMX shell”:
- help :这会显示一个基本的帮助屏幕,其中说明了可用的命令。
- jps / list :类似于JDK中的jps工具,此命令将打印出所有Java进程及其进程ID。
- connect :您可以使用此命令连接到正在运行的JVM进程。
- format :让您指定是使用简单文本格式还是JSON字符串输出。
- 退出 :退出应用程序。
要了解有关cjmx的更多信息,让我们开始一个会话并连接到运行cjmx本身的JVM:
> jps
13198 cjmx.Main
> connect 13198
Connected to local virtual machine 13198
Connection id: rmi://0:0:0:0:0:0:0:1 2
Default domain: DefaultDomain
5 domains registered consisting of 19 total MBeans
>
describe disconnect exit format help invoke mbeans names names sample select status
在>的最后一个出现之后,您会看到cjmx的一个强大功能:自动完成。 每次您不知道可用的命令时,只需键入[TAB]
,cjmx就会列出它们。 我们将看到,这甚至适用于MBean名称。
现在我们已连接到JVM,可以让cjmx描述可用的MBean。 使用自动完成功能,我们可以开始输入describe '[TAB]
来检索所有可用软件包的列表:
> describe '
: JMImplementation: com.sun.management: java.lang: java.nio: java.util.logging:
通过这种方式,我们可以挖掘MBean名称,直到找到所需的内容为止。 在此示例中,我们对MBean'java.lang:type = OperatingSystem'感兴趣:
> describe 'java.lang:type=OperatingSystem'
Object name: java.lang:type=OperatingSystem
-------------------------------------------
Description: Information on the management interface of the MBeanAttributes:MaxFileDescriptorCount: longOpenFileDescriptorCount: longFreePhysicalMemorySize: longCommittedVirtualMemorySize: longFreeSwapSpaceSize: longProcessCpuLoad: doubleProcessCpuTime: longSystemCpuLoad: doubleTotalPhysicalMemorySize: longTotalSwapSpaceSize: longAvailableProcessors: intArch: StringSystemLoadAverage: doubleName: StringVersion: StringObjectName: ObjectName
如我们所见,MBean'java.lang:type = OperatingSystem'提供了有关打开文件数和当前CPU负载等的信息。因此,让我们通过调用名称为的mbeans
命令来查询打开文件数。 MBean以及子命令select
和MBean的属性:
> mbeans 'java.lang:type=OperatingSystem' select OpenFileDescriptorCount
java.lang:type=OperatingSystem
------------------------------OpenFileDescriptorCount: 35
我们甚至可以使用星号而不是属性的具体名称来查询所有可用属性。 请注意,使用向上光标键可以调出最后发出的命令,因此我们不必再次键入该命令。 相反,我们只是将属性名称替换为星号:
> mbeans 'java.lang:type=OperatingSystem' select *
java.lang:type=OperatingSystem
------------------------------MaxFileDescriptorCount: 10240OpenFileDescriptorCount: 36
...
通过使用子命令invoke
我们甚至可以像下面的示例一样调用MBean方法:
> mbeans 'java.lang:type=Memory' invoke gc()
java.lang:type=Memory: null
现在我们知道如何查询属性和调用方法,我们可以开始编写此功能的脚本以监视应用程序。 为了支持这种脚本,cjmx提供了可以将所有“命令”也作为参数传递给应用程序本身的功能,因此您可以通过以下方式调用cjmx(其中<PID>必须由一个具体的过程代替)正在运行的JVM的ID):
java -cp $JAVA_HOME/lib/tools.jar:cjmx_2.10-2.1.0-app.jar cjmx.Main &lt;PID&gt; &quot;mbeans 'java.lang:type=OperatingSystem' select OpenFileDescriptorCount&quot;
java.lang:type=OperatingSystem
------------------------------OpenFileDescriptorCount: 630
有了这些知识,我们可以编写一个简单的bash脚本,该脚本每秒查询JVM以获取打开文件的数量:
#!/bin/bash
while [ true ] ; doecho `date` | tr -d '\n'java -cp /usr/java/default/lib/tools.jar:cjmx_2.10-2.1.0-app.jar cjmx.Main $1 &quot;mbeans 'java.lang:type=OperatingSystem' select OpenFileDescriptorCount&quot;|grep OpenFileDescriptorCount|cut -f 2 -d :sleep 1
done
这会每秒产生一个带有时间戳和当前打开文件数的新行。 当重定向到文件中时,我们有一个简单的日志文件,以后可以对其进行评估。
结论 :当由于服务器计算机上的网络限制而无法使用JConsole时, cjmx是JConsole的绝佳替代品。 通过在命令行上传递命令来发出命令的能力使其适合于小型监视脚本。
翻译自: https://www.javacodegeeks.com/2014/12/cjmx-a-command-line-version-of-jconsole.html