【Java】Java からCPU情報を取得する方法を考える

■ はじめに

https://blogs.yahoo.co.jp/dk521123/7968881.html
の続き。

実装案

【1】コマンドを実行した方法
【2】com.sun.management.OperatingSystemMXBean を使った方法
【3】MBeanServer を使った方法

【1】コマンドの実行結果から取得する方法

Linuxの場合
 * vmstatコマンドでJavaコードから実行し、CPU情報を抽出する
* vmstatコマンドについては、以下の関連記事を参照のこと。
https://blogs.yahoo.co.jp/dk521123/37259054.html

サンプル

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class Main {

  public static void main(String[] args) throws Exception {
    System.out.println("Test1");
    List<Map<String, Long>> vmStatusValues = getVmStatusValues("vmstat");
    System.out.println();
    for (Map<String, Long> vmStatusValue : vmStatusValues) {
      for (Map.Entry<String, Long> map : vmStatusValue.entrySet()) {
        System.out.println(map.getKey() + " : " + map.getValue());
      }
    }

    System.out.println();

    System.out.println("Test2");
    List<Map<String, Long>> vmStatusValues2 = getVmStatusValues("vmstat", "1", "3");
    System.out.println();
    for (Map<String, Long> vmStatusValue : vmStatusValues2) {
      for (Map.Entry<String, Long> map : vmStatusValue.entrySet()) {
        System.out.println(map.getKey() + " : " + map.getValue());
      }
    }
  }

  private static List<Map<String, Long>> getVmStatusValues(String... commands) throws Exception {
    ProcessBuilder processBuilder = new ProcessBuilder(commands);
    try {
      Process process = processBuilder.start();
      int result = process.waitFor();
      System.out.println("Result Code : " + result);

      try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
        String line;
        String[] items = null;
        String[] valuses;
        List<Map<String, Long>> returnValues = new ArrayList<Map<String, Long>>();
        int i = 0;
        while ((line = bufferedReader.readLine()) != null) {
          System.out.println("[DEBUG] " + line);

          i++;
          if (i == 1) {
            // Skip first line
            continue;
          } else if (i == 2) {
            items = line.trim().split("\\s+");
          } else {
            if (items == null) {
              return returnValues;
            }
            valuses = line.trim().split("\\s+");
            Map<String, Long> vmStatusValues = new LinkedHashMap<>();
            int j = 0;
            for (String item : items) {
              Long value = Long.valueOf(valuses[j]);
              vmStatusValues.put(item, value);
              j++;
            }
            returnValues.add(vmStatusValues);
          }
        }
        return returnValues;
      }
    } catch (IOException | InterruptedException ex) {
      throw ex;
    }
  }
}
出力結果
Test1
Result Code : 0
[DEBUG] procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
[DEBUG]  r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
[DEBUG]  2  0 1093384  68964     40 255468   16  137  1921   403  446  548 19  3 78  0  0

r : 2
b : 0
swpd : 1093384
free : 68964
buff : 40
cache : 255468
si : 16
so : 137
bi : 1921
bo : 403
in : 446
cs : 548
us : 19
sy : 3
id : 78
wa : 0
st : 0

Test2
Result Code : 0
[DEBUG] procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
[DEBUG]  r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
[DEBUG]  3  0 1093384  67600     40 256484   16  137  1922   403  446  548 19  3 78  0  0
[DEBUG]  0  0 1093384  65988     40 258092    0    0  1636     0  980 1218 54  6 40  0  0
[DEBUG]  1  0 1093384  65864     40 258128    0    0     0     0  855 1267 54  4 42  0  0

r : 3
b : 0
swpd : 1093384
free : 67600
buff : 40
cache : 256484
si : 16
so : 137
bi : 1922
bo : 403
in : 446
cs : 548
us : 19
sy : 3
id : 78
wa : 0
st : 0
r : 0
b : 0
swpd : 1093384
free : 65988
buff : 40
cache : 258092
si : 0
so : 0
bi : 1636
bo : 0
in : 980
cs : 1218
us : 54
sy : 6
id : 40
wa : 0
st : 0
r : 1
b : 0
swpd : 1093384
free : 65864
buff : 40
cache : 258128
si : 0
so : 0
bi : 0
bo : 0
in : 855
cs : 1267
us : 54
sy : 4
id : 42
wa : 0
st : 0
参考文献
https://stackoverflow.com/questions/6284384/get-memory-and-cpu-usage

【2】com.sun.management.OperatingSystemMXBean を使った方法

サンプル

import java.lang.management.ManagementFactory;

public class Main {
  @SuppressWarnings("restriction")
  public static void main(String[] args) {
    com.sun.management.OperatingSystemMXBean operatingSystemMXBean = 
        (com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
     System.out.println("ProcessCpuLoad : " + operatingSystemMXBean.getProcessCpuLoad());
     System.out.println("ProcessCpuTime : " + operatingSystemMXBean.getProcessCpuTime());
     System.out.println("SystemCpuTime : " + operatingSystemMXBean.getSystemCpuLoad());
  }
}
出力結果
ProcessCpuLoad : -1.0
ProcessCpuTime : 421875000
SystemCpuTime : -1.0
参考文献
https://stackoverflow.com/questions/36647405/java-api-to-get-cpu-memory-usage-of-my-java-application

【3】MBeanServer を使った方法

サンプル

import java.lang.management.ManagementFactory;
import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;

public class Main {
  public static void main(String[] args) throws Exception {
    printCpuInfo();
  }

  public static void printCpuInfo()
      throws InstanceNotFoundException, ReflectionException, MalformedObjectNameException, NullPointerException {
    MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
    ObjectName objectName = ObjectName.getInstance("java.lang:type=OperatingSystem");
    AttributeList attributeList = mbeanServer.getAttributes(objectName,
        new String[] { "ProcessCpuLoad", "ProcessCpuTime", "SystemCpuLoad" });

    if (attributeList.isEmpty()) {
      System.out.println("attributeList is Empty");
    }

    for (Attribute attribute : attributeList.asList()) {
      System.out.println(attribute.getName() + " : " + attribute.getValue());
    }
  }
}
出力結果
ProcessCpuLoad : 0.37238200554819395
ProcessCpuTime : 578125000
SystemCpuLoad : -1.0
参考文献
https://stackoverflow.com/questions/18489273/how-to-get-percentage-of-cpu-usage-of-os-from-java

別解サンプル

import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class Main {
  public static void main(String[] args) {
    printUsage();
  }

  private static void printUsage() {
    OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean();
    for (Method method : operatingSystemMXBean.getClass().getDeclaredMethods()) {
      method.setAccessible(true);
      if (method.getName().startsWith("get") && Modifier.isPublic(method.getModifiers())) {
        Object value;
        try {
          value = method.invoke(operatingSystemMXBean);
        } catch (Exception ex) {
          value = ex;
        }
        System.out.println(method.getName() + " = " + value);
      }
    }
  }
}
出力結果
getCommittedVirtualMemorySize = 236544000
getFreePhysicalMemorySize = 2628100096
getFreeSwapSpaceSize = 2142429184
getProcessCpuLoad = -1.0
getProcessCpuTime = 515625000
getSystemCpuLoad = -1.0
getTotalPhysicalMemorySize = 8491581440
getTotalSwapSpaceSize = 10035085312
参考文献
https://stackoverflow.com/questions/47177/how-do-i-monitor-the-computers-cpu-memory-and-disk-usage-in-java

■その他:別解

 * 以下のサイトで「/proc/stat の出力」を利用した方法があった。
http://maku77.github.io/java/parse-proc-stat.html

関連記事

Java】PCリソース情報(ディスク容量、JVMメモリ容量、CPU情報)を取得する

https://blogs.yahoo.co.jp/dk521123/7968881.html

Java】 外部プログラム/コマンドを実行するには ~ ProcessBuilder ~

https://blogs.yahoo.co.jp/dk521123/34842155.html

JavaJMX (Java Management Extensions) / MBean (Management Bean)

https://blogs.yahoo.co.jp/dk521123/34391290.html