当前位置: 首页 > 面试题库 >

从运行的JVM收集统计信息的API

严兴言
2023-03-14
问题内容

对于一个类项目,我想实现一个Java应用程序,该应用程序连接到本地JVM并收集统计信息,例如堆使用情况,线程数,已加载的类等。我已经在网上搜索API,内置第三方,这将允许我执行此操作,但到目前为止我一直没有成功。

有谁知道一个API,它将允许我连接到正在运行的JVM并收集统计信息?


问题答案:

下列类演示如何连接到正在运行的JVM并建立JMX连接,并在必要时加载JMX代理。它将使用MemoryMXBean打印系统属性(无需JMX即可通过JVM连接工作)和内存使用情况。使用其他MXBean类型进行扩展以打印其他统计信息很容易。

请注意,在Java 9之前,您必须将tools.jarJDK的手动添加到类路径。在模块化软件中,您必须向jdk.attach模块添加依赖项。

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()+"\t"+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("\t"+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:\t");
    MemoryUsage mu=memoryMXBean.getHeapMemoryUsage();
    System.out.println(
      "allocated "+mu.getCommitted()+", used "+mu.getUsed()+", max "+mu.getMax());
    System.out.print("Non-Heap:\t");
    mu=memoryMXBean.getNonHeapMemoryUsage();
    System.out.println(
      "allocated "+mu.getCommitted()+", used "+mu.getUsed()+", max "+mu.getMax());
    System.out.println(
      "Pending Finalizations: "+memoryMXBean.getObjectPendingFinalizationCount());
  }
}

connect上述解决方案的方法需要Java8。较旧的Java版本的替代方案如下所示:

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();
}


 类似资料:
  • 问题内容: 如何从Spider回调中收集统计信息? 例 总体上不确定该import如何stats使用或如何使用。 问题答案: 从scrapy文档中查看统计信息页面。该文档指出Stats Collector,但可能需要添加到你的Spider代码中才能对其进行处理。 EDIT2:经过大量的谷歌搜索,显然没有必要导入。只需使用!

  • 问题内容: 删除和重新创建索引是否与使用dbms.gather_index_stats具有相同的效果?(是否具有与重建/更新索引相同的效果) 还是这两个完全不同的东西不应该相互比较? 问题答案: 区别在于,收集统计信息会刷新有关当前索引的元数据,而删除和重新创建索引则是删除和重新创建索引。 也许通过一个实例可以很容易地理解它们之间的区别。因此,让我们创建一个表和一个索引: 由于11g,Oracle

  • 本文向大家介绍Oracle 11g收集多列统计信息详解,包括了Oracle 11g收集多列统计信息详解的使用技巧和注意事项,需要的朋友参考一下 前言 通常,当我们将SQL语句提交给Oracle数据库时,Oracle会选择一种最优方式来执行,这是通过查询优化器Query Optimizer来实现的。CBO(Cost-Based Optimizer)是Oracle默认使用的查询优化器模式。在CBO中,

  • 是否可以看到被设为null的java对象(及其类类型)以及 尚未收集/清理垃圾 垃圾收集/清理。 此统计信息将有助于了解有多少对象重复创建(通过错误的逻辑)而不是一次性创建。

  • 除了RMI之外,还有其他方法可以收集Tomcat统计信息吗?我想在本地而不是远程监控tomcat。有什么方法吗?或者我应该编写一个自定义MBean来实现这一点? 我知道这个:JMXServiceURL url=newjmxserviceurl(“服务:jmx:rmi:///jndi/rmi://localhost:8081/jmxrmi“”;JMXConnector jmxc=JMXConnect

  • 在本节中,我们将讨论使用Whois Lookup,Netcraft和Robtex收集客户信息的各种技术。然后,我们将看到如何通过定位该服务器上托管的网站来攻击服务器。在信息收集部分,我们将了解子域以及它们如何对执行攻击有用。稍后在目标系统上查找文件以收集一些信息并分析该数据。 现在,我们将在开始尝试利用之前收集信息。因此,我们将尽可能多地收集有关目标IP,网站上使用的技术,域名信息,使用哪种编程语