OSレベルのシステム情報を取得する


232

私は現在、多くの異なるプラットフォームで実行される可能性があるJavaアプリを構築していますが、主にSolaris、Linux、およびWindowsのバリアントです。

現在のディスク使用量、CPU使用率、基盤となるOSで使用されているメモリなどの情報を正常に抽出できた人はいますか?Javaアプリ自体が消費しているものについてはどうですか?

JNIを使​​用せずにこの情報を取得したいのですが。


3
空きメモリ参照のことに関してはstackoverflow.com/a/18366283/231397Runtime.getRuntime().freeMemory()受け入れ答えで提案されているようにあなたの空きメモリの量を与えられたものではありません。
クリスチャン・フリース

回答:


206

Runtimeクラスから限られたメモリ情報を取得できます。それは本当にあなたが探しているものではありませんが、私は完全性のためにそれを提供しようと思っていました。これは小さな例です。編集:java.io.Fileクラスからディスク使用量情報を取得することもできます。ディスク容量の使用には、Java 1.6以降が必要です。

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 available to the JVM */
    System.out.println("Total memory available to JVM (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());
    }
  }
}

7
「JVMが現在使用しているメモリの合計」は少しわかりにくいと思います。javadocツールは、その関数が戻ると言う「バイト単位で測定された現在および将来のオブジェクトに利用可能な現在のメモリーの合計量を。」残りのメモリが使用されていないようです。
Dirk

@Dirk:コメントに対処するために文言を更新しました。ありがとう!
ウィリアムブレンデル

@LeonardoGaldioli:これらのクラスとメソッドのパフォーマンス特性はわかりませんが、速度が最適化されていなくても驚くことはありません。他の回答は、JMXを使用して特定の情報を収集する方法を説明しています。
ウィリアムブレンデル

15
これは質問に正しく答えません。そのデータはすべて、OSではなくJVMに到達します...
Alvaro

このトピックはかなり古くなっています。ただし、CPUコアの量が本当に必要な場合は、このソリューションを使用しないでください。各コアに2つのスレッドがあるデュアルコアCPUを使用しています。JVMはハードウェアコアではなく、ソフトウェアコア/スレッドを返します。
F_Schmidt

95

java.lang.managementのパッケージはあなたのランタイムよりもはるかに多くの情報を与えない-例えば、それはあなたのヒープメモリを与える(ManagementFactory.getMemoryMXBean().getHeapMemoryUsage())(非ヒープメモリとは別ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage())。

あなたはまた、(自分のJNIコードを記述することなく)プロセスのCPU使用率を取得することができますが、キャストする必要がありますjava.lang.management.OperatingSystemMXBeancom.sun.management.OperatingSystemMXBean。これはWindowsとLinuxで動作します。他の場所ではテストしていません。

たとえば、より正確な測定値を取得するには、get getCpuUsage()メソッドをより頻繁に呼び出します。

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();
        }
    }
}

10
コンパイルするには、キャストOperatingSystemMXBeanをに置き換え、のcom.sun.management.OperatingSystemMXBeanすべてのインスタンスの前にをgetOperatingSystemMXBean()付けManagementFactory.ます。すべてのクラスを適切にインポートする必要があります。
tmarthal

2
すべてのCPU使用率を0にしています。cpuの使用式をcpuUsage = processCpuTime / systemTimeに変更しました。理解できないCPU使用率の値を取得しています。
Raj

ない1.0から、結果として、getCpuUsageシステムはそのすべて使用されていることを意味availableProcessorsを 100%?
user454322 2012

2
@Rajが言ったように、私は常に0を取得します...そのコードの使用方法の例を挙げていただけますか?
dm76

1
試してみる((double)( processCpuTime - lastProcessCpuTime )) / ((double)( systemTime - lastSystemTime ))
Anthony O.

43

HypericでSIGAR APIを実装するのが最善の方法だと思います。ほとんどの主要なオペレーティングシステム(ほとんどすべての最新のもの)で動作し、操作が非常に簡単です。開発者は、フォーラムやメーリングリストに非常に敏感です。GPL2 Apacheライセンスであることも好きですます。Javaでの例もたくさんあります!

SIGAR ==システム情報、収集およびレポートツール。


2
@ヨハン-怠惰にしないでください!あなたはリンクされたウェブページを読むことによってそれを見つけることができます。(そして、「プラットフォーム非依存」の意味によって異なります。)
Stephen C

2
@StephenC:Sigarは.dllファイルを使用しているため、プラットフォームに依存しています。より高レベルのAPIはJavaにあるかもしれませんが、それは別の話です
レモンジュース

1
@Artificial_Intelligenceはい、ただし、最も人気のあるプラットフォーム用のライブラリ(cで記述)を提供します。これは、jvm自体よりもプラットフォームに依存しません。より高いレベルのJava APIは、すべてのプラットフォームで一貫している必要があります。
Jeshurun 2013

8
Sigarは2010年以降更新されておらず、64ビットシステムにバグがあるようです
Alvaro

1
また、SIGARはJVMをクラッシュさせます(断続的ですが)が、本番環境ではこのリスクを負わないと思います。
AKS

25

JNAを使用する(インストールするネイティブライブラリがない)Javaプロジェクトがあり、活発に開発中です。現在、Linux、OSX、Windows、Solaris、FreeBSDをサポートしており、RAM、CPU、バッテリー、ファイルシステムの情報を提供します。


おそらくネイティブライブラリは誤解を招くものではありません。プロジェクトネイティブライブラリを使用しますが、それらがまだ作成されていなくても、インストールする必要はないようです。
Stephen C

1
あなたが正しい。JNAは、ネイティブコンポーネントを持つlibffiを使用します。しかし、すべての目的で、ネイティブライブラリがないように見えます(インストールする必要はありません)。
dB。

@StephenCあなたが言うことは正確ですが、ネイティブメソッドを呼び出すrt.jarでも同じであるため、誤解を招きます。人々がネイティブメソッドを気にする唯一の理由は、それらをコンパイルおよび/またはインストールする必要があることです。libffiは非常に広く採用、移植、およびインストールされているため、問題は軽減されます。したがって、技術的には正しいですが、実際には問題ではありません。
rbp

@rbp- 経験豊富な Java開発者がネイティブライブラリを避けることを好む別の理由があります。バグ(スレッドセーフティの問題やメモリ管理の問題を含む)があるネイティブライブラリは、ホストJVMを不安定にする可能性があります。これは問題ではない」問題ではありません ....
Stephen C

@StephenC weblogicアプリケーションサーバーを作成したことで、十分な経験ができますか?
rbp 2013年

13

Windowsの場合は、この方法で行った。

    com.sun.management.OperatingSystemMXBean os = (com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();

    long physicalMemorySize = os.getTotalPhysicalMemorySize();
    long freePhysicalMemory = os.getFreePhysicalMemorySize();
    long freeSwapSize = os.getFreeSwapSpaceSize();
    long commitedVirtualMemorySize = os.getCommittedVirtualMemorySize();

ここにあるリンクの詳細とは。


11

を使用System.getenv()して、関連する環境変数名をパラメーターとして渡すことにより、システムレベルの情報を取得できます。たとえば、Windowsの場合:

System.getenv("PROCESSOR_IDENTIFIER")
System.getenv("PROCESSOR_ARCHITECTURE")
System.getenv("PROCESSOR_ARCHITEW6432")
System.getenv("NUMBER_OF_PROCESSORS")

他のオペレーティングシステムでは、関連する環境変数の有無と名前が異なります。


1
変数名はシステム間で異なるため、これらはプラットフォームに依存します。環境変数に関するOracleの記事はそれを伝えています。システムに依存しない方法を取得する方法も探しています。
レモンジュース

Linux(Ubuntu 17.10)では、環境内のプロセッサに関する興味深い情報はあまりありません。
pveentjer 2017

8

mavenを介してOSHI依存関係を追加します。

<dependency>
    <groupId>com.github.dblock</groupId>
    <artifactId>oshi-core</artifactId>
    <version>2.2</version>
</dependency>

バッテリー残量をパーセンテージで取得します。

SystemInfo si = new SystemInfo();
HardwareAbstractionLayer hal = si.getHardware();
for (PowerSource pSource : hal.getPowerSources()) {
    System.out.println(String.format("%n %s @ %.1f%%", pSource.getName(), pSource.getRemainingCapacity() * 100d));
}

OSHIには、他のコメントに記載されているほとんどの情報があります。可能な場合は、JNAを使用してOSネイティブコール経由で取得します。
Daniel Widdis

6

java.lang.managementパッケージで利用可能なAPIをご覧ください。例えば:

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

他にもたくさんの便利なものがあります。


2
OperatingSystemMXBean.getSystemLoadAverage()は、「高すぎる」ため、Windowsでは実装されていません
MikeNereson 2009

1
ThreadMXBean.getCurrentThreadCpuTime()は、そのスレッドが実行されている時間だけを返します。CPU使用率ではありません。
MikeNereson、2009

5

通常、低レベルのOS情報を取得するには、Runtime.exec()で必要な情報を提供するOS固有のコマンドを呼び出すか、Linuxの/ proc / *などのファイルを読み取ります。


5

CPUの使用率は単純ではありません-com.sun.management.OperatingSystemMXBean.getProcessCpuTimeを介したjava.lang.managementが近づいていますが(上記のPatrickの優れたコードスニペットを参照)、CPUがプロセスで費やした時間にのみアクセスできることに注意してください。他のプロセスに費やされたCPU時間、またはプロセスに関連するシステムアクティビティの実行に費やされたCPU時間については通知しません。

たとえば、ネットワーク集約型のJavaプロセスがあります。これは実行中の唯一のプロセスであり、CPUは99%ですが、その55%だけが「プロセッサCPU」として報告されます。

MX BeanでCPUに関連する唯一のアイテムであるにもかかわらず、「負荷平均」は役に立たないので、私を始めないでください。ときどき知恵の太陽だけが "getTotalCpuTime"のようなものを公開した場合...

深刻なCPU監視には、SIGARがMattによって言及されたのが最善の策のようです。


4

Windows、あなたが実行できるsysteminfoコマンドを、次のコードでインスタンスの出力を取得します。

private static class WindowsSystemInformation
{
    static String get() throws IOException
    {
        Runtime runtime = Runtime.getRuntime();
        Process process = runtime.exec("systeminfo");
        BufferedReader systemInformationReader = new BufferedReader(new InputStreamReader(process.getInputStream()));

        StringBuilder stringBuilder = new StringBuilder();
        String line;

        while ((line = systemInformationReader.readLine()) != null)
        {
            stringBuilder.append(line);
            stringBuilder.append(System.lineSeparator());
        }

        return stringBuilder.toString().trim();
    }
}

3

Jrockit VMを使用している場合、VMのCPU使用率を取得する別の方法を次に示します。ランタイムBeanは、プロセッサーごとのCPU負荷も提供します。私はこれをRed Hat Linuxでのみ使用して、Tomcatのパフォーマンスを監視しました。これを機能させるには、catalina.shでJMXリモートを有効にする必要があります。

JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://my.tomcat.host:8080/jmxrmi");
JMXConnector jmxc = JMXConnectorFactory.connect(url, null);     
MBeanServerConnection conn = jmxc.getMBeanServerConnection();       
ObjectName name = new ObjectName("oracle.jrockit.management:type=Runtime");
Double jvmCpuLoad =(Double)conn.getAttribute(name, "VMGeneratedCPULoad");

3

まだ開発中ですが、jHardwareはすでに使用できます

Javaを使用してシステムデータをスクラップする単純なライブラリです。LinuxとWindowsの両方で動作します。

ProcessorInfo info = HardwareInfo.getProcessorInfo();
//Get named info
System.out.println("Cache size: " + info.getCacheSize());        
System.out.println("Family: " + info.getFamily());
System.out.println("Speed (Mhz): " + info.getMhz());
//[...]

いいですが、私のニーズと矛盾するGuavaとJNAのバージョンを使用しています(例:GLASSFISH-21367を参照)。
lu_ko

こんにちは、JNAはjHardwareの0.8バージョンで導入されました。温度とセンサーのデータにのみ使用されます。その情報が必要ない場合は、0.7バージョンを使用できます。グアバも同じです。その場合は、0.6.3バージョンを使用する必要があります。
profesor_falken 2017

2

OSレベルの情報を取得するために使用できる簡単な方法の1つで、Macでテストしたところ、うまく機能しました。

 OperatingSystemMXBean osBean =
        (OperatingSystemMXBean)ManagementFactory.getOperatingSystemMXBean();
    return osBean.getProcessCpuLoad();

ここには、オペレーティングシステムに関連する多くのメトリックが表示されます。


1

こんにちは、java / com統合でこれを実行できます。WMI機能にアクセスすることで、すべての情報を取得できます。


0

Javaコード内で1分、5分、15分のシステム負荷平均を取得するには、次のようにcat /proc/loadavg使用して解釈するコマンドを実行します。

    Runtime runtime = Runtime.getRuntime();

    BufferedReader br = new BufferedReader(
        new InputStreamReader(runtime.exec("cat /proc/loadavg").getInputStream()));

    String avgLine = br.readLine();
    System.out.println(avgLine);
    List<String> avgLineList = Arrays.asList(avgLine.split("\\s+"));
    System.out.println(avgLineList);
    System.out.println("Average load 1 minute : " + avgLineList.get(0));
    System.out.println("Average load 5 minutes : " + avgLineList.get(1));
    System.out.println("Average load 15 minutes : " + avgLineList.get(2));

そして、コマンドを実行し、それを以下のように解釈して、物理システムメモリを取得free -mします。

Runtime runtime = Runtime.getRuntime();

BufferedReader br = new BufferedReader(
    new InputStreamReader(runtime.exec("free -m").getInputStream()));

String line;
String memLine = "";
int index = 0;
while ((line = br.readLine()) != null) {
  if (index == 1) {
    memLine = line;
  }
  index++;
}
//                  total        used        free      shared  buff/cache   available
//    Mem:          15933        3153        9683         310        3097       12148
//    Swap:          3814           0        3814

List<String> memInfoList = Arrays.asList(memLine.split("\\s+"));
int totalSystemMemory = Integer.parseInt(memInfoList.get(1));
int totalSystemUsedMemory = Integer.parseInt(memInfoList.get(2));
int totalSystemFreeMemory = Integer.parseInt(memInfoList.get(3));

System.out.println("Total system memory in mb: " + totalSystemMemory);
System.out.println("Total system used memory in mb: " + totalSystemUsedMemory);
System.out.println("Total system free memory in mb: "   + totalSystemFreeMemory);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.