API for collecting statistics from running the JVM

For a class project, I would like to implement a Java application that connects to the local JVM and collects statistics such as heap usage, number of threads, loaded classes, etc. I searched the Internet for an API, a third party that would allow me to do this, but I still have not been successful.

Does anyone know an API that will allow me to connect to a running JVM and collect statistics?

+4
source share
3 answers

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 a JVM connection without the need for JMX) and memory usage using a MemoryMXBean. It is easy to expand to print other statistics using other types of MXBean.

Note that prior to Java 9, you must add the tools.jar your JDK to the classpath manually. In modular software, you must 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()+"\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()); } } 

The connect method described above requires Java 8. An alternative for older versions of Java is as follows:

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

VisualVM exposes some of its functions using the Java API. Please note: they are in the com.sun.tools.* Package, and not in the usual java.* Or javax.* .

Take a look at Getting Started VisualVM Extension for more information on how to use these APIs.

+1
source

There is a native api called the JVMTool Interface

If you need statistics from a running JVM, you can use VisualVM , which comes with the JDK. It provides statistics for all running processes on jvm.

0
source

Source: https://habr.com/ru/post/957413/


All Articles