JavaでコンピューターのCPU、メモリ、ディスクの使用状況を監視するにはどうすればよいですか?


180

Javaで次のシステム情報を監視したいと思います。

  • 現在のCPU使用率**(パーセント)
  • 利用可能なメモリ*(無料/合計)
  • 利用可能なディスク容量(無料/合計)

    *私は、JVMだけでなく、システム全体で利用可能なメモリ全体を意味することに注意してください。

私は、自分のコードが外部プログラムを呼び出したりJNIを使​​用したりすることに依存しないクロスプラットフォームソリューション(Linux、Mac、Windows)を探しています。これらは実行可能なオプションですが、誰かがすでにより良い解決策を持っている場合、私はOS固有のコードを自分で維持しないことを望みます。

信頼できるクロスプラットフォームの方法でこれを行う無料のライブラリがあれば、それは素晴らしいことです(外部呼び出しを行ったり、ネイティブコード自体を使用したりする場合でも)。

どんな提案も大歓迎です。

明確にするために、Javaプロセスだけでなく、システム全体の現在のCPU使用率を取得したいと思います。

SIGAR APIは、探しているすべての機能を1つのパッケージで提供するため、これまでの私の質問に対する最良の答えです。ただし、GPLでライセンスされているため、元の目的(クローズドソース、商用製品)には使用できません。HypericがSIGARを商用利用するためのライセンスを取得する可能性はありますが、私は調べていません。私のGPLプロジェクトでは、将来的に間違いなくSIGARを検討します。

私の現在のニーズのために、私は次のことに傾いています。

  • CPU使用率OperatingSystemMXBean.getSystemLoadAverage() / OperatingSystemMXBean.getAvailableProcessors()(CPU あたりの負荷平均)
  • 記憶のために、OperatingSystemMXBean.getTotalPhysicalMemorySize()そしてOperatingSystemMXBean.getFreePhysicalMemorySize()
  • ディスク容量、File.getTotalSpace()およびFile.getUsableSpace()

制限:

getSystemLoadAverage()メソッドを照会し、ディスクスペースまた、Java 6の下でのみ使用可能であり、いくつかのJMX機能は、(それがあることが報告されています。すなわち、すべてのプラットフォームに利用できない場合がgetSystemLoadAverage()-1を返すWindowsの場合)。

もともとGPLの下でライセンスされていましたがApache 2.0変更されました。これは一般に、クローズドソースの商用製品に使用できます。


明確にするために、sigar apiはシステム情報を取得します。jvm情報が必要な場合は、JMXを使用してください。
マットカミングス

SIGARがGPLの下にあることで、SIGARを使用できなくなるわけではなく、単に作者に連絡して代替ライセンスを要求する必要があることを意味します。多くの場合、著者は小額の手数料を受け入れて商用ライセンスを許可します。
アレックトーマス

7
バージョン1.6.4以降、SIGARはApacheライセンスを使用しています。
Soundlink、2011年

個々のプロセッサの負荷を取得する方法を知っていますか?
zcaudate 2012

回答:


67

この投稿で私が述べことに沿って。SIGAR APIの使用をお勧めします。私は自分のアプリケーションの1つでSIGAR APIを使用しています。あなたはそれが安定していて、よくサポートされており、便利な例がたくさんあることがわかります。これは、GPL 2 Apache 2.0ライセンスのオープンソースです。見てみな。あなたのニーズに応えられると思います。

JavaとSigar APIを使用して、メモリ、CPU、ディスク、負荷平均、ネットワークインターフェース情報とメトリック、プロセステーブル情報、ルート情報などを取得できます。


14
Sigarを使用するときは注意してください。x64マシンに問題があります... stackoverflow.com/questions/23405832/…そして、ライブラリは2010年以降更新されていないようです
Alvaro

56

以下はおそらくあなたにCPUとRAMを与えます。詳細については、ManagementFactoryを参照してください。

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

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 e) {
            value = e;
        } // try
        System.out.println(method.getName() + " = " + value);
    } // if
  } // for
}

3
上記のコードの出力例。このコードはJava 1.5で動作します。getCommittedVirtualMemorySize = 28622848 getFreePhysicalMemorySize = 228462592 getFreeSwapSpaceSize = 1129848832 getProcessCpuTime = 390625000 getTotalPhysicalMemorySize = 2147483647 getTotalSwapSpaceSize = 4294967295
blak3r 2009年

AFAIK getProcessCpuTime = 390625000は、そのスレッドが実行されている時間の長さです。これは、プロセッサの使用状況を判断するのにはあまり役に立ちません
MikeNereson、2009

2
実際に信頼できるかどうかはわかりません。4 GBの物理メモリを搭載したWindows XPでは、2 GBしか報告されません(Java 6およびJava 7でテスト済み)。合計スワップサイズも間違っています。
Emmanuel Bourg

4
@EmmanuelBourgは、このトピックを見る人のために文書化するために、これに関連するバグがあります。
セルジオミヒェルス

2
このメソッドはJava 9までうまく機能しましたが、Javaが使用している新しいアクセスチェックフレームワークが原因で、java.lang.reflect.InaccessibleObjectExceptionがスローされるようになりました。
トールランカスター

40

JDK 1.7では、システムのCPUとメモリの使用量をから取得できますcom.sun.management.OperatingSystemMXBean。これはとは異なり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.

5
これはヒットとミスのようです。取得-1 CPU負荷のためのFreeBSD 10とOpenJDKの8上
CEN

この質問を確認してください。stackoverflow.com/q/19781087/1206998。効果が出るまでに数秒かかるそうです。(注:私は試しませんでした)
Juh_

25

これは、外部Javaがなくても完全に機能し、ネイティブJavaの隠し機能だけです:)

import com.sun.management.OperatingSystemMXBean;
...
OperatingSystemMXBean osBean = ManagementFactory.getPlatformMXBean(
                OperatingSystemMXBean.class);
// What % CPU load this current JVM is taking, from 0.0-1.0
System.out.println(osBean.getProcessCpuLoad());

// What % load the overall system is at, from 0.0-1.0
System.out.println(osBean.getSystemCpuLoad());

私は正直にこれが最良の答えだと思います。Linuxで動作するので、私は幸せです。
ArsenArsen 2016年

1
2回目の呼び出しで0.0が表示される理由は何ですか?OpenJDK v8。
vorburger 2017

忘れないでください: "import java.lang.management.ManagementFactory;"
Bernd

1
getProcessCpuLoadおよびgetSystemCpuLoadは、-1を返します。imはjdk 1.8を使用
BurakAkyıldız2018

スレッド数を取得するメソッドはありませんか?なぜだろう?
djangofan 2018年

16

この非常に詳細な記事をご覧ください:http ://nadeausoftware.com/articles/2008/03/java_tip_how_get_cpu_and_user_time_benchmarking#UsingaSuninternalclasstogetJVMCPUtime

使用されているCPUの割合を取得するために必要なのは、いくつかの簡単な計算です。

MBeanServerConnection mbsc = ManagementFactory.getPlatformMBeanServer();

OperatingSystemMXBean osMBean = ManagementFactory.newPlatformMXBeanProxy(
mbsc, ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME, OperatingSystemMXBean.class);

long nanoBefore = System.nanoTime();
long cpuBefore = osMBean.getProcessCpuTime();

// Call an expensive task, or sleep if you are monitoring a remote process

long cpuAfter = osMBean.getProcessCpuTime();
long nanoAfter = System.nanoTime();

long percent;
if (nanoAfter > nanoBefore)
 percent = ((cpuAfter-cpuBefore)*100L)/
   (nanoAfter-nanoBefore);
else percent = 0;

System.out.println("Cpu usage: "+percent+"%");

注:インポートする必要がありますcom.sun.management.OperatingSystemMXBeanありませんjava.lang.management.OperatingSystemMXBean


これは本当に良い答えです。他のすべての手法は本当に奇妙で信頼性の低い結果をもたらしますが、いくつかの後続平均を伴うこの手法は、私にとって魅力のように機能しました。
Fractaly

cpu時間が経過時間よりも長い場合(100%を超える)、それはマルチスレッドのためか、それをどのように理解するためですか?
Lukas Hanacek

8

ディスク容量については、Java 6を使用している場合は、FilegetTotalSpaceメソッドとgetFreeSpaceメソッドを使用できます。Java 6を使用していない場合は、Apache Commons IOを使用していくつかの方法を実行できると思います。

私が恐れているCPU使用率またはメモリ使用率を取得するためのクロスプラットフォームの方法を知りません。


6

これの多くは、JMXを介してすでに利用可能です。Java 5では、JMXが組み込まれており、JDKにJMXコンソールビューアが含まれています。

JMXを使用して手動で監視するか、独自のランタイムでこの情報が必要な場合はJavaからJMXコマンドを呼び出すことができます。



4
/* YOU CAN TRY THIS TOO */

import java.io.File;
 import java.lang.management.ManagementFactory;
// import java.lang.management.OperatingSystemMXBean;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.lang.management.RuntimeMXBean;
 import java.io.*;
 import java.net.*;
 import java.util.*;
 import java.io.LineNumberReader;
 import java.lang.management.ManagementFactory;
import com.sun.management.OperatingSystemMXBean;
import java.lang.management.ManagementFactory;
import java.util.Random;



 public class Pragati
 {

     public static void printUsage(Runtime runtime)
     {
     long total, free, used;
     int mb = 1024*1024;

     total = runtime.totalMemory();
     free = runtime.freeMemory();
     used = total - free;
     System.out.println("\nTotal Memory: " + total / mb + "MB");
     System.out.println(" Memory Used: " + used / mb + "MB");
     System.out.println(" Memory Free: " + free / mb + "MB");
     System.out.println("Percent Used: " + ((double)used/(double)total)*100 + "%");
     System.out.println("Percent Free: " + ((double)free/(double)total)*100 + "%");
    }
    public static void log(Object message)
         {
            System.out.println(message);
         }

        public static int calcCPU(long cpuStartTime, long elapsedStartTime, int cpuCount)
        {
             long end = System.nanoTime();
             long totalAvailCPUTime = cpuCount * (end-elapsedStartTime);
             long totalUsedCPUTime = ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime()-cpuStartTime;
             //log("Total CPU Time:" + totalUsedCPUTime + " ns.");
             //log("Total Avail CPU Time:" + totalAvailCPUTime + " ns.");
             float per = ((float)totalUsedCPUTime*100)/(float)totalAvailCPUTime;
             log( per);
             return (int)per;
        }

        static boolean isPrime(int n)
        {
     // 2 is the smallest prime
            if (n <= 2)
            {
                return n == 2;
            }
     // even numbers other than 2 are not prime
            if (n % 2 == 0)
            {
                return false;
            }
     // check odd divisors from 3
     // to the square root of n
         for (int i = 3, end = (int)Math.sqrt(n); i <= end; i += 2)
         {
            if (n % i == 0)
         {
         return false;
        }
        }
 return true;
}
    public static void main(String [] args)
    {
            int mb = 1024*1024;
            int gb = 1024*1024*1024;
             /* PHYSICAL MEMORY USAGE */
             System.out.println("\n**** Sizes in Mega Bytes ****\n");
            com.sun.management.OperatingSystemMXBean operatingSystemMXBean = (com.sun.management.OperatingSystemMXBean)ManagementFactory.getOperatingSystemMXBean();
            //RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
            //operatingSystemMXBean = (com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
            com.sun.management.OperatingSystemMXBean os = (com.sun.management.OperatingSystemMXBean)
            java.lang.management.ManagementFactory.getOperatingSystemMXBean();
            long physicalMemorySize = os.getTotalPhysicalMemorySize();
            System.out.println("PHYSICAL MEMORY DETAILS \n");
            System.out.println("total physical memory : " + physicalMemorySize / mb + "MB ");
            long physicalfreeMemorySize = os.getFreePhysicalMemorySize();
            System.out.println("total free physical memory : " + physicalfreeMemorySize / mb + "MB");
            /* DISC SPACE DETAILS */
            File diskPartition = new File("C:");
            File diskPartition1 = new File("D:");
            File diskPartition2 = new File("E:");
            long totalCapacity = diskPartition.getTotalSpace() / gb;
            long totalCapacity1 = diskPartition1.getTotalSpace() / gb;
            double freePartitionSpace = diskPartition.getFreeSpace() / gb;
            double freePartitionSpace1 = diskPartition1.getFreeSpace() / gb;
            double freePartitionSpace2 = diskPartition2.getFreeSpace() / gb;
            double usablePatitionSpace = diskPartition.getUsableSpace() / gb;
            System.out.println("\n**** Sizes in Giga Bytes ****\n");
            System.out.println("DISC SPACE DETAILS \n");
            //System.out.println("Total C partition size : " + totalCapacity + "GB");
            //System.out.println("Usable Space : " + usablePatitionSpace + "GB");
            System.out.println("Free Space in drive C: : " + freePartitionSpace + "GB");
            System.out.println("Free Space in drive D:  : " + freePartitionSpace1 + "GB");
            System.out.println("Free Space in drive E: " + freePartitionSpace2 + "GB");
            if(freePartitionSpace <= totalCapacity%10 || freePartitionSpace1 <= totalCapacity1%10)
            {
                System.out.println(" !!!alert!!!!");
            }
            else
                System.out.println("no alert");

            Runtime runtime;
            byte[] bytes;
            System.out.println("\n \n**MEMORY DETAILS  ** \n");
            // Print initial memory usage.
            runtime = Runtime.getRuntime();
            printUsage(runtime);

            // Allocate a 1 Megabyte and print memory usage
            bytes = new byte[1024*1024];
            printUsage(runtime);

            bytes = null;
            // Invoke garbage collector to reclaim the allocated memory.
            runtime.gc();

            // Wait 5 seconds to give garbage collector a chance to run
            try {
            Thread.sleep(5000);
            } catch(InterruptedException e) {
            e.printStackTrace();
            return;
            }

            // Total memory will probably be the same as the second printUsage call,
            // but the free memory should be about 1 Megabyte larger if garbage
            // collection kicked in.
            printUsage(runtime);
            for(int i = 0; i < 30; i++)
                     {
                         long start = System.nanoTime();
                        // log(start);
                        //number of available processors;
                         int cpuCount = ManagementFactory.getOperatingSystemMXBean().getAvailableProcessors();
                         Random random = new Random(start);
                         int seed = Math.abs(random.nextInt());
                         log("\n \n CPU USAGE DETAILS \n\n");
                         log("Starting Test with " + cpuCount + " CPUs and random number:" + seed);
                         int primes = 10000;
                         //
                         long startCPUTime = ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime();
                         start = System.nanoTime();
                         while(primes != 0)
                         {
                            if(isPrime(seed))
                            {
                                primes--;
                            }
                            seed++;

                        }
                         float cpuPercent = calcCPU(startCPUTime, start, cpuCount);
                         log("CPU USAGE : " + cpuPercent + " % ");


                         try
                         {
                             Thread.sleep(1000);
                         }
                         catch (InterruptedException e) {}
        }

            try
            {
                Thread.sleep(500);
            }`enter code here`
            catch (Exception ignored) { }
        }
    }

4

次のコードはLinux(おそらくUnix)のみですが、実際のプロジェクトで機能します。

    private double getAverageValueByLinux() throws InterruptedException {
    try {

        long delay = 50;
        List<Double> listValues = new ArrayList<Double>();
        for (int i = 0; i < 100; i++) {
            long cput1 = getCpuT();
            Thread.sleep(delay);
            long cput2 = getCpuT();
            double cpuproc = (1000d * (cput2 - cput1)) / (double) delay;
            listValues.add(cpuproc);
        }
        listValues.remove(0);
        listValues.remove(listValues.size() - 1);
        double sum = 0.0;
        for (Double double1 : listValues) {
            sum += double1;
        }
        return sum / listValues.size();
    } catch (Exception e) {
        e.printStackTrace();
        return 0;
    }

}

private long getCpuT throws FileNotFoundException, IOException {
    BufferedReader reader = new BufferedReader(new FileReader("/proc/stat"));
    String line = reader.readLine();
    Pattern pattern = Pattern.compile("\\D+(\\d+)\\D+(\\d+)\\D+(\\d+)\\D+(\\d+)")
    Matcher m = pattern.matcher(line);

    long cpuUser = 0;
    long cpuSystem = 0;
    if (m.find()) {
        cpuUser = Long.parseLong(m.group(1));
        cpuSystem = Long.parseLong(m.group(3));
    }
    return cpuUser + cpuSystem;
}

1
これは実際に私が探していたものですが、コードに/ proc / statからCPU情報を見つけるためのREGEXパターンがありません
Donal Tobin

パターンは何ですか?
HCarrasko、2015年

3

typeperf -sc 1 "\ mukit \ processor(_Total)\ %% Processor Time"としてバッチファイル "Pc.bat"を作成します

クラスMProcessを使用できます。

/ *
 * Md。ムキットハサン
 * CSE-JU、35
 ** / javaをインポートします。io 。*;

パブリッククラスMProcessor {

public MProcessor() { String s; try { Process ps = Runtime.getRuntime().exec("Pc.bat"); BufferedReader br = new BufferedReader(new InputStreamReader(ps.getInputStream())); while((s = br.readLine()) != null) { System.out.println(s); } } catch( Exception ex ) { System.out.println(ex.toString()); } }

}

次に、文字列を操作した後、CPUを使用します。他のタスクにも同じプロセスを使用できます。

--Mukit Hasan


1
私(Win XP)の適切なコマンドラインは次のとおりtypeperf "\processor(_total)\% processor time"です。バッチファイルに配置する場合は、%ではなく%%を使用します。technet.microsoft.com/en-us/library/bb490960.aspxを使用しました。
tutejszy 2013年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.