Monitor the use of the CPU in the Java application

zhaozj2021-02-16  55

How do I get the use of CPU in Java? There is also a good news and a bad news here. The bad news is the use of the CPU without the use of pure Java. There is no direct API in this area. A suggested alternative is to determine the JVM process ID (PID) to determine the JVM process ID (PID), call the external, platform-related commands, such as PS, and then resolve the PID of interested interest in the run. However, this method is not ideal. The good news is that a more reliable solution can be used: jump out of Java, write a few line C code, and then integrate with JNI. Below I will show you a simple JNi library written in a Win32 platform. In general, JNI is a bit complicated. However, if you only calls only one-way call - from Java calls local code, and only the basic type is communicating - things are still very simple. There are many JNI learning materials, so I will not introduce the foundation of JNI here. I only introduce my implementation steps. 1. In Java, the JNI method is declared, I created a class com.vladium.utils.systeminformation declared the local method, which returns milliseconds of the CPU used by the current process.

Public Staticnative Long getProcessCputime ();

The Javah tool built into JDK generates the C header that will be implemented in the future.

JNIEXPORT JLONG JNICALLJAVA_COM_VLADIUM_UTILS_SYSTEMINFORMATION_GETPROCESSCPUTIME (JNIENV * ENV, JCLASS CLS)

Second, the local method is implemented on most Win32 platforms, which can be implemented using the getProceSstimes () system call implementation, almost only need 3 lines of code:

JNIEXPORT jlong ​​JNICALLJava_com_vladium_utils_SystemInformation_getProcessCPUTime (JNIEnv * env, jclass cls) {FILETIME creationTime, exitTime, kernelTime, userTime; GetProcessTimes (s_currentProcess, & creationTime, & exitTime, & kernelTime, & userTime); return (jlong) ((fileTimeToInt64 (& kernelTime) FileTimetoinT64 (& Usertime)) / (s_numberofprocessors * 10000));

This method first accumulates the core and user code consumption of the current process, divided by the number of processors, and converts the results to milliseconds. FileTimetoint64 () is an auxiliary function that converts the file of the FileTime structure to a 64-bit integer. S_CurrentProcess and S_NumberOfProcessors are global variables that are initialized when the JVM is loaded locally.

static HANDLE s_currentProcess; static int s_numberOfProcessors; JNIEXPORT jint JNICALLJNI_OnLoad (JavaVM * vm, void * reserved) {SYSTEM_INFO systemInfo; s_currentProcess = GetCurrentProcess (); GetSystemInfo (& systemInfo); s_numberOfProcessors = systemInfo.dwNumberOfProcessors; return JNI_VERSION_1_2;} Note that if you GetProcessCputime () is implemented on the UNIX platform, you should start with the getRusage system call. Third, call the local method Back to Java, in the SystemInformation class, load the local library (Silib.dll On Win32) is best done by static initialization code block.

private static final String SILIB = "silib"; static {try {System.loadLibrary (SILIB);} catch (UnsatisfiedLinkError e) {System.out.println ( "native lib '" SILIB "' not found in 'java. Library.path ': " System.GetProperty (" java.library.path "); throw e; // re-throw}}

Note that getProcessCPutime () returns the CPU time used since the JVM process created. As far as this data itself, there is not much place for this. I need more useful Java methods to record Data Snapshots, and report the use of CPUs between two points in time.

public static final class CPUUsageSnapshot {private CPUUsageSnapshot (long time, long CPUTime) {m_time = time; m_CPUTime = CPUTime;} public final long m_time, m_CPUTime;} // end of nested class public static CPUUsageSnapshot makeCPUUsageSnapshot () {return new CPUUsageSnapshot ( System.currentTimeMillis (), getProcessCPUTime ());} public static double getProcessCPUUsage (CPUUsageSnapshot start, CPUUsageSnapshot end) {return ((double) (end.m_CPUTime - start.m_CPUTime)) / (end.m_time - start.m_time); } Fourth, a simple CPU monitor "CPU monitoring API" is basically completed! Finally, I created a Singleton thread class CPUusageThread that automatically took a data snapshot every time interval (default 0.5 seconds), and reported to all CPU listeners (Observer mode).

public void run () {while {final SystemInformation.CPUUsageSnapshot snapshot = SystemInformation.makeCPUUsageSnapshot () (isInterrupted ()!); notifyListeners (snapshot); try {sleep (sleepTime);} catch (InterruptedException e) {return;}}}

The CPUMON class is an example listener that simply prints the usage of the CPU to System.out. [code] public static void main (string [] args) throws exception {if (args.length == 0) throw new illegalargumentException ("Usage: cpumon

");

CPUUSAGETHREAD MONITOR = CPUUSAGETHREAD.GETCPUTHREADUSAGETHREAD (); cpumon _this = new cpumon ();

Class App = Class.Forname (Args [0]);

Method AppMain = App.getMethod ("main", new class [] {string []. Class});

String [] appargs = new string [args.length - 1]; System.Arraycopy (args, 1, appargs, 0, apparent.length); Monitor.AddusageEventListener (_this); Monitor.Start (); appmain.invoke (null New Object [] {appargs};} [/ code] In addition, in order to start cpuusagethread before starting the application to be monitored, cpumon.main () is packaged another Java primary class.

As a demonstration, I run the SwingSet2 sample program for CPumon and JDK1.3.1 (don't forget to install Silib.dll to the path environment variable over the OS or the path over from the java.library.path system properties):

> java -djava.library.path =. -CP Silib.jar; (My JDK Install Dir) /Demo/jfc/swingset2/swingset2.jar cpumon swingset2

[PID: 339] CPU usage: 46.8%

[PID: 339] CPU usage: 51.4%

[PID: 339] CPU usage: 54.8%

(While Loading, The Demo Uses Nearly 100% of One of the Two CPUS on My Machine)

...

[PID: 339] CPU usage: 46.8%

[PID: 339] CPU usage: 0%

[PID: 339] CPU usage: 0%

(The demo finished loading all of its panels and is most iDLE)

...

[PID: 339] CPU USAGE: 100%

[PID: 339] CPU usage: 98.4%

[PID: 339] CPU usage: 97%

(I switched to the colorchooserdemo Panel Which Ran A CPU-Intensive

Animation That Used Both Of My CPUS)

...

[PID: 339] CPU usage: 81.4%

[PID: 339] CPU usage: 50%

[PID: 339] CPU usage: 50%

(I used windows nt task manager to adjut the cpu affinity for the cpu affinity

"Java" Process to Use A Single CPU)

...

Of course, I can also see the CPU usage information through the task manager, the main point of this is now we can program the information in programming. For long-term running tests and server application diagnostics, it will send it later. Other useful local methods have been added to the complete library included in this article, one of which can be pid (for integration with external tools).

From-javaworld.com javaresearch translation

转载请注明原文地址:https://www.9cbs.com/read-15380.html

New Post(0)