API to gather statistics from running JVM(用于从正在运行的 JVM 收集统计信息的 API)
问题描述
对于一个类项目,我想实现一个 Java 应用程序,它连接到本地 JVM 并收集诸如堆使用情况、线程数、加载的类等统计信息.我在网上搜索了一个 API,第三方内置的,可以让我这样做,但到目前为止我还没有成功.
For a class project, I would like to implement a Java application that connects to a local JVM and gathers statistics such as heap usage, number of threads, loaded classes etc. I've searched online for an API, third party of built-in, that would allow me to do this but I have so far been unsuccessful.
有谁知道可以让我连接到正在运行的 JVM 并收集统计数据的 API?
Does anyone know of an API that will allow me to connect to a running JVM and gather statistics?
推荐答案
以下类演示了如何连接到正在运行的 JVM 并建立 JMX 连接,并在必要时加载 JMX 代理.它将打印系统属性(这通过 JVM 连接工作,无需 JMX)和使用 MemoryMXBean 的内存使用情况.使用其他 MXBean 类型可以轻松扩展以打印其他统计信息.
The following class demonstrates how to connect to a running JVM and establish a JMX connection, loading the JMX agent if necessary. It will print System Properties (this works through the JVM connection without the need for JMX) and the memory usage using the MemoryMXBean. It’s easy to extend to print other statistics using other MXBean types.
注意,在 Java 9 之前,您必须手动将 JDK 的 tools.jar
添加到类路径中.在模块化软件中,您必须向 jdk.attach
模块添加依赖项.
Note, that before Java 9, you have to add the tools.jar
of your JDK to the classpath manually. In modular software, you have to add a dependency to the jdk.attach
module.
import static java.lang.management.ManagementFactory.MEMORY_MXBEAN_NAME;
import static java.lang.management.ManagementFactory.newPlatformMXBeanProxy;
import java.io.*;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.util.*;
import javax.management.MBeanServerConnection;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import com.sun.tools.attach.*;
public class CmdLineTool
{
static final String CONNECTOR_ADDRESS =
"com.sun.management.jmxremote.localConnectorAddress";
public static void main(String[] args)
{
if(args.length!=1)
System.err.println("Usage: java CmdLineTool <pid>");
else if(printStats(args[0])) return;
System.out.println("Currently running");
for(VirtualMachineDescriptor vmd:VirtualMachine.list())
System.out.println(vmd.id()+" "+vmd.displayName());
}
private static boolean printStats(String id)
{
try
{
VirtualMachine vm=VirtualMachine.attach(id);
System.out.println("Connected to "+vm.id());
System.out.println("System Properties:");
for(Map.Entry<?,?> en:vm.getSystemProperties().entrySet())
System.out.println(" "+en.getKey()+" = "+en.getValue());
System.out.println();
try
{
MBeanServerConnection sc=connect(vm);
MemoryMXBean memoryMXBean =
newPlatformMXBeanProxy(sc, MEMORY_MXBEAN_NAME, MemoryMXBean.class);
getRamInfoHtml(memoryMXBean);
} catch(IOException ex)
{
System.out.println("JMX: "+ex);
}
vm.detach();
return true;
} catch(AttachNotSupportedException | IOException ex)
{
ex.printStackTrace();
}
return false;
}
// requires Java 8, alternative below the code
static MBeanServerConnection connect(VirtualMachine vm) throws IOException
{
String connectorAddress = vm.startLocalManagementAgent();
JMXConnector c=JMXConnectorFactory.connect(new JMXServiceURL(connectorAddress));
return c.getMBeanServerConnection();
}
static void getRamInfoHtml(MemoryMXBean memoryMXBean)
{
System.out.print("Heap: ");
MemoryUsage mu=memoryMXBean.getHeapMemoryUsage();
System.out.println(
"allocated "+mu.getCommitted()+", used "+mu.getUsed()+", max "+mu.getMax());
System.out.print("Non-Heap: ");
mu=memoryMXBean.getNonHeapMemoryUsage();
System.out.println(
"allocated "+mu.getCommitted()+", used "+mu.getUsed()+", max "+mu.getMax());
System.out.println(
"Pending Finalizations: "+memoryMXBean.getObjectPendingFinalizationCount());
}
}
上述解决方案的 connect
方法需要 Java 8.旧 Java 版本的替代方案看起来像
The connect
method of above solution requires Java 8. The alternative for older Java versions looks like
static MBeanServerConnection connect(VirtualMachine vm) throws IOException
{
String connectorAddress = vm.getAgentProperties().getProperty(CONNECTOR_ADDRESS);
if(connectorAddress == null)
{
System.out.println("loading agent");
Properties props = vm.getSystemProperties();
String home = props.getProperty("java.home");
String agent = home+File.separator+"lib"+File.separator+"management-agent.jar";
try {
vm.loadAgent(agent);
} catch (AgentLoadException|AgentInitializationException ex) {
throw new IOException(ex);
}
connectorAddress = vm.getAgentProperties().getProperty(CONNECTOR_ADDRESS);
while(connectorAddress==null) try {
Thread.sleep(1000);
connectorAddress = vm.getAgentProperties().getProperty(CONNECTOR_ADDRESS);
} catch(InterruptedException ex){}
}
JMXConnector c=JMXConnectorFactory.connect(new JMXServiceURL(connectorAddress));
return c.getMBeanServerConnection();
}
这篇关于用于从正在运行的 JVM 收集统计信息的 API的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:用于从正在运行的 JVM 收集统计信息的 API


- 如何使用WebFilter实现授权头检查 2022-01-01
- value & 是什么意思?0xff 在 Java 中做什么? 2022-01-01
- 从 finally 块返回时 Java 的奇怪行为 2022-01-01
- 将log4j 1.2配置转换为log4j 2配置 2022-01-01
- C++ 和 Java 进程之间的共享内存 2022-01-01
- Safepoint+stats 日志,输出 JDK12 中没有 vmop 操作 2022-01-01
- Jersey REST 客户端:发布多部分数据 2022-01-01
- Java包名称中单词分隔符的约定是什么? 2022-01-01
- Eclipse 插件更新错误日志在哪里? 2022-01-01
- Spring Boot连接到使用仲裁器运行的MongoDB副本集 2022-01-01