JVM外部调试工具:JMXTerm


JMX 公开了管理“bean”(MBean),这些是表示应用程序中控制点的对象。您的应用程序可以发布自己的 bean,这让您可以公开运行时监控和配置的功能。这非常酷,因为您可以导出管理员可以直接连接到仪表板(APM、Prometheus、Grafana 等)的信息并将其用于决策。
JMX 是一个了不起的工具,我们主要用于连接管理控制台。这很了不起,您应该为您的项目大量导出 JMX 设置。话虽如此,您可以通过将 JMX 作为调试过程的一部分将其提升到一个新的水平。
服务器应用程序在没有 UI 或深度 UI 分离的情况下运行。JMX 通常可以用作用户界面的一种形式,甚至可以用作命令行界面,如JMXTerm. 在这些情况下,我们可以在管理 UI 中触发调试情况或观察调试会话的结果。

JMXTerm帮助认识服务器内部运行细节,我们可以JMXTerm从这里下载开始。

下载后,我们可以使用它连接到服务器:

java -jar ~/Downloads/jmxterm-1.0.2-uber.jar --url localhost:30002

您应该根据您的连接更新主机名/端口。连接后,我们可以使用提示列出 JMX 域:

> domains following domains are available JMImplementation com.sun.management java.lang java.nio java.util.logging javax.cache jdk.management.jfr

然后我们可以选择一个特定的域来探索。这就是视觉工具通常有益的地方,因为它可以为您提供更快的层次结构导航和信息的快速评估。在这种情况下,我只想设置日志记录级别:

> domain java.util.logging domain is set to java.util.logging


我们可以通过列出域中的 bean 来遵循这一点。然后选择我们希望使用的 bean,因为在这个特定域中只有一个 bean:

> beans domain = java.util.logging: java.util.logging:type=Logging
> bean java.util.logging:type=Logging bean is set to java.util.logging:type=Logging

能用这个bean做什么?为此,我们有 info 命令列出了 bean 的操作和属性:

> info mbean = java.util.logging:type=Logging #class name = sun.management.ManagementFactoryHelper$PlatformLoggingImpl # attributes %0 - LoggerNames ([Ljava.lang.String;, r) %1 - ObjectName (javax.management.ObjectName, r) # operations %0 - java.lang.String getLoggerLevel(java.lang.String p0) %1 - java.lang.String getParentLoggerName(java.lang.String p0) %2 - void setLoggerLevel(java.lang.String p0,java.lang.String p1) there's no notifications

一旦我有了这些,我可以检查当前的记录器级别,它没有设置,因为我们没有明确设置它并且使用全局默认值:

> run getLoggerLevel "org.apache.tomcat.websocket.WsWebSocketContainer" calling operation getLoggerLevel of mbean java.util.logging:type=Logging with params [org.apache.tomcat.websocket.WsWebSocketContainer] operation returns: 

我可以将其显式设置为 INFO,然后再次获取它以使用以下代码验证操作是否按预期工作:

> run setLoggerLevel org.apache.tomcat.websocket.WsWebSocketContainer INFO calling operation setLoggerLevel of mbean java.util.logging:type=Logging with params [org.apache.tomcat.websocket.WsWebSocketContainer, INFO] operation returns: null
> run getLoggerLevel "org.apache.tomcat.websocket.WsWebSocketContainer" calling operation getLoggerLevel of mbean java.util.logging:type=Logging with params [org.apache.tomcat.websocket.WsWebSocketContainer] operation returns: INFO

这只是冰山一角。我们可以得到很多东西,比如spring设置,内部VM信息等等。在这个例子中我可以直接从控制台查询VM信息:

> domain com.sun.management domain is set to com.sun.management
> beans domain = com.sun.management: com.sun.management:type=DiagnosticCommand com.sun.management:type=HotSpotDiagnostic
> bean com.sun.management:type=HotSpotDiagnostic bean is set to com.sun.management:type=HotSpotDiagnostic
> info mbean = com.sun.management:type=HotSpotDiagnostic #class name = com.sun.management.internal.HotSpotDiagnostic # attributes %0 - DiagnosticOptions ([Ljavax.management.openmbean.CompositeData;, r) %1 - ObjectName (javax.management.ObjectName, r) # operations %0 - void dumpHeap(java.lang.String p0,boolean p1) %1 - javax.management.openmbean.CompositeData getVMOption(java.lang.String p0) %2 - void setVMOption(java.lang.String p0,java.lang.String p1) there's no notifications