OSレベルのシステム情報を取得する
質問
私は現在、さまざまなプラットフォームで実行できる Java アプリを構築していますが、主に Solaris、Linux、Windows の亜種です。
現在使用されているディスク容量、CPU 使用率、基盤となる OS で使用されているメモリなどの情報を正常に抽出できた人はいますか?Java アプリ自体が消費しているものはどうなるのでしょうか?
できれば JNI を使用せずにこの情報を取得したいと考えています。
解決
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());
}
}
}
他のヒント
の java.lang.management パッケージは、ランタイムよりもはるかに多くの情報を提供します。たとえば、ヒープ メモリが提供されます (ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()
) 非ヒープ メモリから分離 (ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage()
).
(独自の JNI コードを作成しなくても) プロセスの CPU 使用率を取得することもできますが、 java.lang.management.OperatingSystemMXBean
に com.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();
}
}
}
最善の方法は、 Hyperic の SIGAR API. 。ほとんどの主要なオペレーティング システム (最新のものに近いもの) で動作し、非常に簡単に操作できます。開発者はフォーラムやメーリング リストで非常に敏感です。それも気に入っています GPL2 Apache ライセンス済み. 。Java の例も豊富に提供されています。
JNA を使用する Java プロジェクトがあり (ネイティブ ライブラリをインストールする必要はありません)、現在開発中です。現在、Linux、OSX、Windows、Solaris、FreeBSD をサポートしており、RAM、CPU、バッテリー、ファイル システム情報を提供します。
次を使用して、システムレベルの情報を取得できます。 System.getenv()
, 、関連する環境変数名をパラメータとして渡します。たとえば、Windows では次のようになります。
System.getenv("PROCESSOR_IDENTIFIER")
System.getenv("PROCESSOR_ARCHITECTURE")
System.getenv("PROCESSOR_ARCHITEW6432")
System.getenv("NUMBER_OF_PROCESSORS")
その他のオペレーティングシステムでは、該当する環境変数の有無や名称が異なります。
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();
ここにあります リンク 詳細付き。
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));
}
で利用可能な API をご覧ください。 java.lang.management パッケージ。例えば:
OperatingSystemMXBean.getSystemLoadAverage()
ThreadMXBean.getCurrentThreadCpuTime()
ThreadMXBean.getCurrentThreadUserTime()
他にも便利なものがたくさんあります。
通常、低レベルの OS 情報を取得するには、Runtime.exec() で必要な情報を提供する OS 固有のコマンドを呼び出すか、Linux の /proc/* などのファイルを読み取ることができます。
CPU 使用率は単純ではありません。com.sun.management.OperatingSystemMXBean.getProcessCpuTime 経由の java.lang.management がそれに近いものですが (上記の Patrick の優れたコード スニペットを参照)、これはプロセスで CPU が費やした時間にしかアクセスできないことに注意してください。他のプロセスに費やされた CPU 時間や、プロセスに関連するシステム アクティビティに費やされた CPU 時間さえもわかりません。
たとえば、ネットワークを集中的に使用する Java プロセスがあります。これが唯一実行されており、CPU は 99% ですが、そのうちの 55% だけが「プロセッサ CPU」として報告されます。
「ロードアベレージ」は、MX Bean の唯一の CPU 関連項目であるにもかかわらず、ほとんど役に立たないため、始めさせないでください。太陽が時々の知恵で「getTotalCpuTime」のようなものを公開していたら...
本格的な CPU 監視には、Matt が言及した SIGAR が最善の策のようです。
まだ開発中ですが、すでに使用できます jハードウェア
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());
//[...]
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");
の上 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();
}
}
OS レベルの情報を取得するために使用できる 1 つの簡単な方法。私の Mac でテストしましたが、うまくいきました。
OperatingSystemMXBean osBean =
(OperatingSystemMXBean)ManagementFactory.getOperatingSystemMXBean();
return osBean.getProcessCpuLoad();
オペレーティング システムの関連するメトリクスを多数見つけることができます。 ここ
java/com 統合を使用すると、これを行うことができます。WMI 機能にアクセスすると、すべての情報を取得できます。