用于从正在运行的 JVM 收集统计信息的 API [英] API to gather statistics from running JVM

查看:17
本文介绍了用于从正在运行的 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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆