Starting with Java 5, the JDK provides some API for JVM detection, which is known as the Java.lang.management package, which provides many Mxbean interface classes that can be easily retrieved to the JVM's memory, GC, Thread, lock, class, Even the operating system level of various information, this article is a simple introduction of the use of JMX on the Java process CPU, heap memory usage monitoring. Some people may find it unnecessary to do so, because tools like jconsole can do it and are more detailed than the examples in this article. But there are times when the console may not be able to monitor the Java process as a system service, and I have recently had to encode myself to get the monitoring data for the remote Java process. Hope to play a role in it.
First, a brief introduction to the JMX (Java Management Extensions), the Java Management extension, is used to monitor and manage the JVM and the operating system it runs. At present, the Java platform mainly provides the 9 Mxbean shown, the role of each mxbean according to the class name can probably guess a few, specifically to check the API.
The Mxbean in the Java.lang.management package provides basic functionality, enhancements to some features in Sum.com.management, and, of course, our own mxbean in accordance with the JMX specification.
Below I mainly use Java.lang.management.MemoryMXBean and Sun.com.management.OperatingSystemMXBean respectively for the remote Java memory and CPU monitoring. The data is read 5 seconds according to the requirement, the memory is mainly used heap memory,cpu mainly is the usage rate.
Before using Operatingsystemmxbean and Memorymxbean, you must first get jmxconnector and create mbeanserverconnnection, With this connection we can use Managementfactory to create the required Mxbean, and the class dependency graph is as follows:
Example code:
Java code
- /*
- * Host: IP address of the remote machine
- * Port: Jmxremote port run by remote Java process
- */
- Jmxserviceurl serviceurl = new Jmxserviceurl (Host,port);
- Jmxconnector conn = Jmxconnectorfactory.connect (serviceurl);
- Mbeanserverconnection mbs=conn.getmbeanserverconnection ();
- Get remote Memorymxbean
- Memorymxbean Membean=managementfactory.newplatformmxbeanproxy
- (Mbs,managementfactory.memory_mxbean_name, Memorymxbean. class);
- Get remote Opretingsystemmxbean
- Com.sun.management.OperatingSystemMXBean Opmxbean =
- Managementfactory.newplatformmxbeanproxy (MBS,
- Managementfactory.operating_system_mxbean_name, Operatingsystemmxbean. class);
Then, the memory data acquisition is relatively simple, the direct call API to obtain:
Java code
- /** Collect data every 5 seconds */
- try {
- TimeUnit.SECONDS.sleep (5);
- } catch (Interruptedexception e) {
- Logger.error ("interruptedexception occurred while memorycollector sleeping ...");
- }
- Memoryusage heap = Membean
- Etheapmemoryusage ();
- Memoryusage nonheap = Membean
- Etnonheapmemoryusage ();
- Long heapsizeused = heap.getused (); //size of heap use
- Long nonheapsizeused = nonheap.getused ();
- Long heapcommitedsize = heap.getcommitted ();
- Long nonheapcommitedsize = nonheap.getcommitted ();
CPU utilization needs to be calculated, because the API only provides the use of CPU time, I have to two times in the system time interval to obtain two CPU usage time, the time interval for CPU use, division is the CPU usage, of course, the error must exist.
Calculate CPU Usage Code
- Long start = System.currenttimemillis ();
- Long Startt = Opmxbean.getprocesscputime ();
- /** Collect data every 5 seconds * /
- try {
- TimeUnit.SECONDS.sleep (5);
- } catch (Interruptedexception e) {
- Logger.error ("interruptedexception occurred while memorycollector sleeping ...");
- }
- Long end = System.currenttimemillis ();
- Long Endt = Opmxbean.getprocesscputime ();
- End-start is the current collection of time units, Unit ms
- Endt-startt the time of the CPU used in the current time unit, in NS
- So: double ratio = (ENTT-STARTT)/1000000.0/(End-start)/opmxbean.getavailableprocessors ()
The core code is these, of course, the specific use of the words should be separated by a separate thread CPU, memory data, read the data need to write files or drawings, monitoring time is also timed to brush these data to disk files or databases, etc., these are off-topic. This way I write to Excel, and then graphically in Excel, the remote monitoring program is not easy to display, just to monitor a program to simulate the CPU sine curve , to see if I monitor the data (graphics) is consistent with the expected, and jconsole to the difference:
Program to be tested, analog CPU sinusoidal code
- public class Sincpu {
- public static final Double time = 1000;
- /**
- * @param args the command line arguments
- */
- public static void Main (string[] args) throws Interruptedexception {
- New Thread (New Sintask ()). Start ();
- }
- Static class Sintask implements runnable{
- @Override
- public void Run () {
- Double x = 0;
- Double y = 0;
- while (true) {
- y = (Math.sin (x) + 1) * Time/ 2;
- Dosomesimplework (y);
- x + = 0.1;
- try {
- Thread.Sleep ((Long) (time-y));
- } catch (Interruptedexception e) {
- E.printstacktrace ();
- }
- }
- }
- private void Dosomesimplework (double y) {
- Long startTime = System.currenttimemillis ();
- while ((System.currenttimemillis ()-startTime) < Y) {
- }
- }
- }
- }
The monitoring results are basically the same as expected, and the CPU data graph renders the expected sinusoidal curve:
, the first figure is cut from the Jconsole monitoring chart, but I use the Opmxbean calculation obtained, two graphs basically coincide, the data basic fluctuation in the 0-25% is because I test the machine is a quad-core CPU, two images have a displacement is because, I opened the jconsole manually without my program monitoring to come fast, so probably the image translation under the Basic Agreement.
The memory should be tested more than the CPU, which is not posted here. NOTE: If you monitor a large number of program threads, the CPU will have a more obvious error, and the frequency is not high enough to be a bit of a leak.
Finally: The test program must be open jmxremote port, the specific use of parameters:
-dcom.sun.management.jmxremote-dcom.sun.management.jmxremote.port=[Open Ports]
-dcom.sun.management.jmxremote.authenticate=false
-dcom.sun.management.jmxremote.ssl=false
Using JMX to count the CPU and memory of remote Java processes