In JDK 1.7, you can get system CPU and memory usage via com.sun.management.OperatingSystemMXBean
. This is different than java.lang.management.OperatingSystemMXBean
.
long getCommittedVirtualMemorySize() // Returns the amount of virtual memory that is guaranteed to be available to the running process in bytes, or -1 if this operation is not supported. long getFreePhysicalMemorySize() // Returns the amount of free physical memory in bytes. long getFreeSwapSpaceSize() // Returns the amount of free swap space in bytes. double getProcessCpuLoad() // Returns the "recent cpu usage" for the Java Virtual Machine process. long getProcessCpuTime() // Returns the CPU time used by the process on which the Java virtual machine is running in nanoseconds. double getSystemCpuLoad() // Returns the "recent cpu usage" for the whole system. long getTotalPhysicalMemorySize() // Returns the total amount of physical memory in bytes. long getTotalSwapSpaceSize() // Returns the total amount of swap space in bytes.
Источник
how to get cpu load linux java in percent precise and easy way?
The CPU percentage is then the relative cpu time between the last and the current second divided by the timestamp difference. Here's a simple example implementation of a CpuStats Class:
public class CpuStats < private final long threadId; private long lastCpuTime = 0; private long lastPoll = 0; /** * Creates a CpuStats object for a single thread. * @param threadId The id of the thread to monitor * */ public CpuStats (long threadId) < this.threadId = threadId; lastCpuTime = getTotalTime (); lastPoll = System.nanoTime (); >/** * Creates a CpuStatus object for all threads. The supplied statistics affect * all threads in the current VM. */ public CpuStats () < threadId = -1; lastCpuTime = getTotalTime (); lastPoll = System.nanoTime (); >private long getRelativeTime () < long currentCpuTime = getTotalTime (); long ret = currentCpuTime - lastCpuTime; lastCpuTime = currentCpuTime; return ret; >public double getUsage () < long timeBefore = this.lastPoll; lastPoll = System.nanoTime (); long relTime = getRelativeTime (); return Math.max ((double)relTime / (double)(lastPoll - timeBefore), 0.0); >private long getTotalTime () < if (threadId == -1) < long cpuTime = 0; for (long id : ManagementFactory.getThreadMXBean ().getAllThreadIds ()) < cpuTime += ManagementFactory.getThreadMXBean ().getThreadCpuTime (id); >return cpuTime; > else < return ManagementFactory.getThreadMXBean ().getThreadCpuTime (threadId); >> >
Источник
CPU load from Java
getSystemLoadAverage() gives you value over 1 minute of time (refreshes every second) and gives this value for overall operating system. More realtime overview should be done by monitoring each thread separately. Important is also notice the monitoring refresh interval - more often you check the value, more precice it is in given moment and if you do it every millisecond, it is typically 0 or 100 (or more depending how many CPU's is there). But if we allow timeframe (for example 1 second), we get avarage over this period of time and we get more informative result. Also, it is important to notice, that it is highly unlikely, that only one thread occupies more than one CPU (core).
Following implementation allows to use 3 methods:
- getTotalUsage() - Total load by all the threads in JVM
- getAvarageUsagePerCPU() - Avarage load per CPU (core)
- getUsageByThread(Thread t) - Total load by specified thread
import java.lang.management.ManagementFactory; import java.lang.management.OperatingSystemMXBean; import java.lang.management.ThreadMXBean; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; public class MonitoringThread extends Thread < private long refreshInterval; private boolean stopped; private MapthreadTimeMap = new HashMap(); private ThreadMXBean threadBean = ManagementFactory.getThreadMXBean(); private OperatingSystemMXBean opBean = ManagementFactory.getOperatingSystemMXBean(); public MonitoringThread(long refreshInterval) < this.refreshInterval = refreshInterval; setName("MonitoringThread"); start(); >@Override public void run() < while(!stopped) < SetmappedIds; synchronized (threadTimeMap) < mappedIds = new HashSet(threadTimeMap.keySet()); > long[] allThreadIds = threadBean.getAllThreadIds(); removeDeadThreads(mappedIds, allThreadIds); mapNewThreads(allThreadIds); Collection values; synchronized (threadTimeMap) < values = new HashSet(threadTimeMap.values()); > for (ThreadTime threadTime : values) < synchronized (threadTime) < threadTime.setCurrent(threadBean.getThreadCpuTime(threadTime.getId())); >> try < Thread.sleep(refreshInterval); >catch (InterruptedException e) < throw new RuntimeException(e); >for (ThreadTime threadTime : values) < synchronized (threadTime) < threadTime.setLast(threadTime.getCurrent()); >> > > private void mapNewThreads(long[] allThreadIds) < for (long id : allThreadIds) < synchronized (threadTimeMap) < if(!threadTimeMap.containsKey(id)) threadTimeMap.put(id, new ThreadTime(id)); >> > private void removeDeadThreads(Set mappedIds, long[] allThreadIds) < outer: for (long id1 : mappedIds) < for (long id2 : allThreadIds) < if(id1 == id2) continue outer; >synchronized (threadTimeMap) < threadTimeMap.remove(id1); >> > public void stopMonitor() < this.stopped = true; >public double getTotalUsage() < Collectionvalues; synchronized (threadTimeMap) < values = new HashSet(threadTimeMap.values()); > double usage = 0D; for (ThreadTime threadTime : values) < synchronized (threadTime) < usage += (threadTime.getCurrent() - threadTime.getLast()) / (refreshInterval * 10000); >> return usage; > public double getAvarageUsagePerCPU() < return getTotalUsage() / opBean.getAvailableProcessors(); >public double getUsageByThread(Thread t) < ThreadTime info; synchronized (threadTimeMap) < info = threadTimeMap.get(t.getId()); >double usage = 0D; if(info != null) < synchronized (info) < usage = (info.getCurrent() - info.getLast()) / (refreshInterval * 10000); >> return usage; > static class ThreadTime < private long id; private long last; private long current; public ThreadTime(long id) < this.id = id; >public long getId() < return id; >public long getLast() < return last; >public void setLast(long last) < this.last = last; >public long getCurrent() < return current; >public void setCurrent(long current) < this.current = current; >> >
Источник
java cpu usage monitoring
There is a gem in the comments on the article which kgiannakakis linked:
JavaSysMon manages processes and reports useful system performance metrics cross-platform. You can think of it as a cross-platform version of the UNIX `top’ command, along with the ability to kill processes. It comes in the form of a single JAR file /..
-works on Windows, Mac OS X, Linux, and Solaris.
How about using jmx mbeans?
final OperatingSystemMXBean myOsBean= ManagementFactory.getOperatingSystemMXBean(); double load = myOsBean.getSystemLoadAverage();
docs says -1 means not supported. But on linux I get value less than what OS says, so I assume it is the CPU load used by current JVM?
You can use jMX beans to calculate a CPU load. Note that this measures CPU load of your java program, not the overall system load. (the question didn't specify which)
ThreadMXBean newBean = ManagementFactory.getThreadMXBean(); try < if (this.newBean.isThreadCpuTimeSupported()) this.newBean.setThreadCpuTimeEnabled(true); else throw new AccessControlException(""); >catch (AccessControlException e)
Then as your loop (assuming your application uses a loop, otherwise what's the point in measuring CPU usage?) use this:
long lastTime = System.nanoTime(); long lastThreadTime = newBean.getCurrentThreadCpuTime(); while (true) < // Do something that takes at least 10ms (on windows) try < int j = 0; for (int i = 0; i < 20000000; i++) j = (j + i) * j / 2; Thread.sleep(100); >catch (InterruptedException e) < >// Calculate coarse CPU usage: long time = System.nanoTime(); long threadTime = newBean.getCurrentThreadCpuTime(); double load = (threadTime - lastThreadTime) / (double)(time - lastTime); System.out.println((float)load); // For next iteration. lastTime = time; lastThreadTime = threadTime; >
You need to use double precision because a long doesn't fit in a float (though it might work 99.9999999999999999% of the time)
If the 'something' you're doing takes less than approximately 1.6ms (Windows), then the returned value will not even have increased at all and you'll perpetually measure 0% CPU erroneously.
Because getCurrentThreadCpuTime is VERY inaccurate (with delays less than 100ms), smoothing it helps a lot:
long lastTime = System.nanoTime(); long lastThreadTime = newBean.getCurrentThreadCpuTime(); float smoothLoad = 0; while (true) < // Do something that takes at least 10ms (on windows) try < int j = 0; for (int i = 0; i < 2000000; i++) j = (j + i) * j / 2; Thread.sleep(10); >catch (InterruptedException e) < >// Calculate coarse CPU usage: long time = System.nanoTime(); long threadTime = newBean.getCurrentThreadCpuTime(); double load = (threadTime - lastThreadTime) / (double)(time - lastTime); // Smooth it. smoothLoad += (load - smoothLoad) * 0.1; // damping factor, lower means less responsive, 1 means no smoothing. System.out.println(smoothLoad); // For next iteration. lastTime = time; lastThreadTime = threadTime; >
Источник
How to get percentage of CPU usage of OS from java
But it gives the cpu load but not the cpu usage. Is there anyway to find the usage percentage?
Can you link to Javadoc for the OperatingSystemMXBean please? Is percentage calculated from load or vice versa? I do not know, but it might be.
2 Answers 2
In Java 7 you can get it like so:
public static double getProcessCpuLoad() throws Exception < MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); ObjectName name = ObjectName.getInstance("java.lang:type=OperatingSystem"); AttributeList list = mbs.getAttributes(name, new String[]< "ProcessCpuLoad" >); if (list.isEmpty()) return Double.NaN; Attribute att = (Attribute)list.get(0); Double value = (Double)att.getValue(); // usually takes a couple of seconds before we get real values if (value == -1.0) return Double.NaN; // returns a percentage value with 1 decimal point precision return ((int)(value * 1000) / 10.0); >
Does this only work on certain operating systems? Running Java 7u15 on 64bit Windows 7, NaN is returned, as value is negative one.
It should work on all. I tested it on Window 7 Java7u51 64bit and it works fine after a few seconds. The first few seconds return -1.0 because it takes some time to initialize some of the objects/values.
Interesting, it seems to take about one second on my machine for the CPU load to be an actual value. Thanks for the clarification. +1
ProcessCpuLoad is the % CPU load of that JVM for the system. there is also SystemCpuLoad which gives the load of the whole system. did you try to call it in a loop? I noticed that the first few calls return -1.0
Источник