对于一个类项目,我想实现一个Java应用程序,它连接到本地JVM并收集统计信息,例如堆使用情况、线程数、加载的类等。我在网上搜索了一个API,第三方内置,这将使我能够做到这一点,但到目前为止我还没有成功。
有谁知道有一个 API 可以让我连接到正在运行的 JVM 并收集统计信息吗?
以下课程演示如何连接到正在运行的 JVM 并建立 JMX 连接,并在必要时加载 JMX 代理。它将使用 MemoryMXBean 打印系统属性(这通过 JVM 连接进行,无需 JMX)和内存使用情况。它\xe2\x80\x99s 很容易扩展以使用其他 MXBean 类型打印其他统计信息。
\n\n请注意,在 Java\xc2\xa09 之前,您必须tools.jar手动将您的 JDK 添加到类路径中。在模块化软件中,您必须向jdk.attach模块添加依赖项。
import static java.lang.management.ManagementFactory.MEMORY_MXBEAN_NAME;\nimport static java.lang.management.ManagementFactory.newPlatformMXBeanProxy;\n\nimport java.io.*;\nimport java.lang.management.MemoryMXBean;\nimport java.lang.management.MemoryUsage;\nimport java.util.*;\n\nimport javax.management.MBeanServerConnection;\nimport javax.management.remote.JMXConnector;\nimport javax.management.remote.JMXConnectorFactory;\nimport javax.management.remote.JMXServiceURL;\n\nimport com.sun.tools.attach.*;\n\npublic class CmdLineTool\n{\n static final String CONNECTOR_ADDRESS =\n "com.sun.management.jmxremote.localConnectorAddress";\n\n public static void main(String[] args)\n {\n if(args.length!=1)\n System.err.println("Usage: java CmdLineTool <pid>");\n else if(printStats(args[0])) return;\n System.out.println("Currently running");\n for(VirtualMachineDescriptor vmd:VirtualMachine.list())\n System.out.println(vmd.id()+"\\t"+vmd.displayName());\n }\n\n private static boolean printStats(String id)\n {\n try\n {\n VirtualMachine vm=VirtualMachine.attach(id);\n System.out.println("Connected to "+vm.id());\n System.out.println("System Properties:");\n for(Map.Entry<?,?> en:vm.getSystemProperties().entrySet())\n System.out.println("\\t"+en.getKey()+" = "+en.getValue());\n System.out.println();\n try\n {\n MBeanServerConnection sc=connect(vm);\n MemoryMXBean memoryMXBean =\n newPlatformMXBeanProxy(sc, MEMORY_MXBEAN_NAME, MemoryMXBean.class);\n getRamInfoHtml(memoryMXBean);\n } catch(IOException ex)\n {\n System.out.println("JMX: "+ex);\n }\n vm.detach();\n return true;\n } catch(AttachNotSupportedException | IOException ex)\n {\n ex.printStackTrace();\n }\n return false;\n }\n // requires Java 8, alternative below the code\n static MBeanServerConnection connect(VirtualMachine vm) throws IOException\n {\n String connectorAddress = vm.startLocalManagementAgent();\n JMXConnector c=JMXConnectorFactory.connect(new JMXServiceURL(connectorAddress));\n return c.getMBeanServerConnection();\n }\n\n static void getRamInfoHtml(MemoryMXBean memoryMXBean)\n {\n System.out.print("Heap:\\t");\n MemoryUsage mu=memoryMXBean.getHeapMemoryUsage();\n System.out.println(\n "allocated "+mu.getCommitted()+", used "+mu.getUsed()+", max "+mu.getMax());\n System.out.print("Non-Heap:\\t");\n mu=memoryMXBean.getNonHeapMemoryUsage();\n System.out.println(\n "allocated "+mu.getCommitted()+", used "+mu.getUsed()+", max "+mu.getMax());\n System.out.println(\n "Pending Finalizations: "+memoryMXBean.getObjectPendingFinalizationCount());\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\nconnect上述解决方法需要Java\xc2\xa08 。旧 Java 版本的替代方案如下所示
static MBeanServerConnection connect(VirtualMachine vm) throws IOException\n{\n String connectorAddress = vm.getAgentProperties().getProperty(CONNECTOR_ADDRESS);\n if(connectorAddress == null)\n {\n System.out.println("loading agent");\n Properties props = vm.getSystemProperties();\n String home = props.getProperty("java.home");\n String agent = home+File.separator+"lib"+File.separator+"management-agent.jar";\n try {\n vm.loadAgent(agent);\n } catch (AgentLoadException|AgentInitializationException ex) {\n throw new IOException(ex);\n }\n connectorAddress = vm.getAgentProperties().getProperty(CONNECTOR_ADDRESS);\n while(connectorAddress==null) try {\n Thread.sleep(1000);\n connectorAddress = vm.getAgentProperties().getProperty(CONNECTOR_ADDRESS);\n } catch(InterruptedException ex){}\n }\n JMXConnector c=JMXConnectorFactory.connect(new JMXServiceURL(connectorAddress));\n return c.getMBeanServerConnection();\n}\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
4738 次 |
| 最近记录: |