2013-10-16 47 views
4

对于类项目,我想实现一个Java应用程序,该应用程序连接到本地JVM并收集统计信息,如堆使用情况,线程数,加载的类等。我在线搜索对于一个API,内置的第三方,这将允许我这样做,但我迄今没有成功。API从运行的JVM收集统计信息

有谁知道一个API,可以让我连接到正在运行的JVM并收集统计信息吗?

+0

JMX不是用于这个目的吗? – RandomQuestion

+1

http://stackoverflow.com/questions/856881/how-to-activate-jmx-on-my-jvm-for-access-with-jconsole – dnault

+0

这可能也有帮助。 http://docs.oracle.com/javase/7/docs/technotes/guides/management/agent.html – RandomQuestion

回答

3

以下类演示如何连接到正在运行的JVM并建立JMX连接,并根据需要加载JMX代理。它将使用MemoryMXBean打印系统属性(这通过JVM连接工作,不需要JMX)和内存使用情况。使用其他MXBean类型扩展可以轻松地打印其他统计信息。

请注意,您必须手动将JDK的tools.jar添加到类路径中。

import static java.lang.management.ManagementFactory.MEMORY_MXBEAN_NAME; 
import static java.lang.management.ManagementFactory.newPlatformMXBeanProxy; 

import java.io.File; 
import java.io.IOException; 
import java.lang.management.MemoryMXBean; 
import java.lang.management.MemoryUsage; 
import java.util.Map; 
import java.util.Properties; 

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); 
     System.out.println(); 
     getRamInfoHtml(memoryMXBean); 
     } catch(AgentLoadException | AgentInitializationException ex) 
     { 
     System.out.println("JMX: "+ex); 
     } 
     vm.detach(); 
     return true; 
    } catch(AttachNotSupportedException | IOException ex) 
    { 
     ex.printStackTrace(); 
    } 
    return false; 
    } 
    static MBeanServerConnection connect(VirtualMachine vm) 
    throws AgentLoadException, AgentInitializationException, 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"; 
     vm.loadAgent(agent); 
     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(); 
    } 
    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()); 
    } 
} 
0

有一个叫JVMTool Interface

如果你想从一个正在运行的JVM的统计数据,你可以使用VisualVM,它随JDK的本地API。它为jvm上的所有正在运行的进程提供统计信息。

1

VisualVM通过Java API公开了它的一些功能。请注意,这些是在com.sun.tools.*包中,而不是通常的java.*javax.*包。

有关如何使用这些API的更多信息,请参见Getting Started Extending VisualVM