tags:

views:

14095

answers:

8

I'm currently building a Java app that could end up being run on many different platforms, but primarily variants of Solaris, Linux and Windows.

Has anyone been able to successfully extract information such as the current disk space used, CPU utilisation and memory used in the underlying OS? What about just what the Java app itself is consuming?

Preferrably I'd like to get this information without using JNI.

+9  A: 

I think the best method out there is to implement the SIGAR API by Hyperic. It works for most of the major operating systems ( darn near anything modern ) and is very easy to work with. The developer(s) are very responsive on their forum and mailing lists. I also like that it is GPL2. They provide a ton of examples in Java too!

SIGAR == System Information, Gathering And Reporting tool.

Matt Cummings
+21  A: 

You can get some limited memory information from the Runtime class. It really isn't exactly what you are looking for, but I thought I would provide it for the sake of completeness. Here is a small example. Edit: You can also get disk usage information from the java.io.File class. The disk space usage stuff requires Java 1.6 or higher.

public class Main {
  public static void main(String[] args) {
    /* Total number of processors or cores available to the JVM */
    System.out.println("Available processors (cores): " + 
        Runtime.getRuntime().availableProcessors());

    /* Total amount of free memory available to the JVM */
    System.out.println("Free memory (bytes): " + 
        Runtime.getRuntime().freeMemory());

    /* This will return Long.MAX_VALUE if there is no preset limit */
    long maxMemory = Runtime.getRuntime().maxMemory();
    /* Maximum amount of memory the JVM will attempt to use */
    System.out.println("Maximum memory (bytes): " + 
        (maxMemory == Long.MAX_VALUE ? "no limit" : maxMemory));

    /* Total memory currently in use by the JVM */
    System.out.println("Total memory (bytes): " + 
        Runtime.getRuntime().totalMemory());

    /* Get a list of all filesystem roots on this system */
    File[] roots = File.listRoots();

    /* For each filesystem root, print some info */
    for (File root : roots) {
      System.out.println("File system root: " + root.getAbsolutePath());
      System.out.println("Total space (bytes): " + root.getTotalSpace());
      System.out.println("Free space (bytes): " + root.getFreeSpace());
      System.out.println("Usable space (bytes): " + root.getUsableSpace());
    }
  }
}
William Brendel
+3  A: 

Have a look at the APIs available in the java.lang.management package. For example:

  • OperatingSystemMXBean.getSystemLoadAverage()
  • ThreadMXBean.getCurrentThreadCpuTime()
  • ThreadMXBean.getCurrentThreadUserTime()

There are loads of other useful things in there as well.

staffan
OperatingSystemMXBean.getSystemLoadAverage() is not implemented in windows because "its too expensive"
MikeNereson
ThreadMXBean.getCurrentThreadCpuTime() only returns how long that thread has been running. Not the cpu usage percentage.
MikeNereson
+20  A: 

The java.lang.management package does give you a whole lot more info than Runtime - for example it will give you heap memory (ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()) separate from non-heap memory (ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage()).

You can also get process CPU usage (without writing your own JNI code), but you need to cast the java.lang.management.OperatingSystemMXBean to a com.sun.management.OperatingSystemMXBean. This works on Windows and Linux, I haven't tested it elsewhere.

For example ... call the get getCpuUsage() method more frequently to get more accurate readings.

public class PerformanceMonitor { 
    private int  availableProcessors = getOperatingSystemMXBean().getAvailableProcessors();
    private long lastSystemTime      = 0;
    private long lastProcessCpuTime  = 0;

    public synchronized double getCpuUsage()
    {
        if ( lastSystemTime == 0 )
        {
            baselineCounters();
            return;
        }

    long systemTime     = System.nanoTime();
    long processCpuTime = 0;

    if ( getOperatingSystemMXBean() instanceof OperatingSystemMXBean )
    {
        processCpuTime = ( (OperatingSystemMXBean) getOperatingSystemMXBean() ).getProcessCpuTime();
    }

    double cpuUsage = (double) ( processCpuTime - lastProcessCpuTime ) / ( systemTime - lastSystemTime );

    lastSystemTime     = systemTime;
    lastProcessCpuTime = processCpuTime;

    return cpuUsage / availableProcessors;
}

private void baselineCounters()
{
    lastSystemTime = System.nanoTime();

    if ( getOperatingSystemMXBean() instanceof OperatingSystemMXBean )
    {
        lastProcessCpuTime = ( (OperatingSystemMXBean) getOperatingSystemMXBean() ).getProcessCpuTime();
    }
}

}

Patrick Wilkes
The code doesn't compile...
futureelite7
A: 

Hey you can do this with java/com integration. By accessing WMI features you can get all the information.

+1  A: 

Usually, to get low level OS information you can call OS specific commands which give you the information you want with Runtime.exec() or read files such as /proc/* in Linux.

Peter Lawrey
+2  A: 

CPU usage isn't straightforward -- java.lang.management via com.sun.management.OperatingSystemMXBean.getProcessCpuTime comes close (see Patrick's excellent code snippet above) but note that it only gives access to time the CPU spent in your process. it won't tell you about CPU time spent in other processes, or even CPU time spent doing system activities related to your process.

for instance i have a network-intensive java process -- it's the only thing running and the CPU is at 99% but only 55% of that is reported as "processor CPU".

don't even get me started on "load average" as it's next to useless, despite being the only cpu-related item on the MX bean. if only sun in their occasional wisdom exposed something like "getTotalCpuTime"...

for serious CPU monitoring SIGAR mentioned by Matt seems the best bet.

Partly Cloudy
A: 

There's a new native Java project that uses JNA (so no native libraries). It's very young and needs contributions.

dblock