关于java:获取操作系统级别的系统信息

关于java:获取操作系统级别的系统信息

get OS-level system information

我目前正在构建一个Java应用程序,该应用程序最终可能在许多不同的平台上运行,但主要是Solaris,Linux和Windows的变体。

是否有人能够成功提取信息,例如当前使用的磁盘空间,底层操作系统中使用的CPU使用率和内存? Java应用程序本身正在消耗什么呢?

最好我不使用JNI来获取此信息。


您可以从Runtime类中获取一些有限的内存信息。确实不是您要找的东西,但我想为完整起见会提供它。这是一个小例子。编辑:您还可以从java.io.File类获取磁盘使用情况信息。磁盘空间使用情况需要Java 1.6或更高版本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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())分开的信息。

您还可以获取进程CPU的使用情况(而无需编写自己的JNI代码),但是您需要将java.lang.management.OperatingSystemMXBean强制转换为com.sun.management.OperatingSystemMXBean。这可以在Windows和Linux上使用,我没有在其他地方进行过测试。

例如,...更频繁地调用get getCpuUsage()方法以获得更准确的读数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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示例!

SIGAR ==系统信息,收集和报告工具。


有一个Java项目使用JNA(因此无需安装本机库)并且正在积极开发中。它目前支持Linux,OSX,Windows,Solaris和FreeBSD,并提供RAM,CPU,电池和文件系统信息。

  • https://github.com/oshi/oshi

对于Windows,我采用这种方式。

1
2
3
4
5
6
    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();

这是详细信息的链接。


您可以通过使用System.getenv()并将相关的环境变量名称作为参数来获取一些系统级信息。例如,在Windows上:

1
2
3
4
System.getenv("PROCESSOR_IDENTIFIER")
System.getenv("PROCESSOR_ARCHITECTURE")
System.getenv("PROCESSOR_ARCHITEW6432")
System.getenv("NUMBER_OF_PROCESSORS")

对于其他操作系统,相关环境变量的存在/不存在和名称将有所不同。


通过maven添加OSHI依赖项:

1
2
3
4
5
<dependency>
    <groupId>com.github.dblock</groupId>
    oshi-core</artifactId>
    <version>2.2</version>
</dependency>

获得剩余的电池电量百分比:

1
2
3
4
5
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));
}

看一下java.lang.management包中的可用API。例如:

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

那里还有许多其他有用的东西。


CPU的使用并不简单-通过com.sun.management.OperatingSystemMXBean.getProcessCpuTime的java.lang.management接近(请参见上面的Patrick出色的代码片段),但请注意,它仅提供访问CPU在进程中花费的时间的权限。它不会告诉您其他进程花费的CPU时间,甚至不会告诉您执行与您的进程相关的系统活动所花费的CPU时间。

例如,我有一个网络密集型的Java进程-它是唯一运行的进程,CPU占99%,但是据报告只有55%是"处理器CPU"。

尽管它是MX bean上唯一与CPU相关的项目,但它甚至让我从"平均负载"开始,因为它几乎没有用。如果只有太阳在他们偶尔的智慧中暴露出诸如" getTotalCpuTime"之类的东西...

Matt提到对SIGAR进行认真的CPU监视似乎是最好的选择。


通常,要获取底层OS信息,您可以调用特定于OS的命令,这些命令可以通过Runtime.exec()为您提供所需的信息,或者在Linux中读取诸如/ proc / *之类的文件。


Windows上,可以运行systeminfo命令并使用以下代码检索其输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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();
    }
}


它仍在开发中,但您已经可以使用jHardware

这是一个简单的库,可使用Java刮取系统数据。它可以在Linux和Windows中使用。

1
2
3
4
5
6
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());
//[...]

一种可以用来获取操作系统级别信息的简单方法,我在Mac上进行了测试,效果很好:

1
2
3
 OperatingSystemMXBean osBean =
        (OperatingSystemMXBean)ManagementFactory.getOperatingSystemMXBean();
    return osBean.getProcessCpuLoad();

您可以在此处找到操作系统的许多相关指标


如果您使用的是Jrockit VM,则这是获取VM CPU使用率的另一种方法。运行时bean还可为您提供每个处理器的CPU负载。我仅在Red Hat Linux上使用过此功能来观察Tomcat的性能。您必须在catalina.sh中启用JMX remote才能起作用。

1
2
3
4
5
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");

嘿,您可以通过java / com集成来做到这一点。通过访问WMI功能,您可以获得所有信息。


推荐阅读