Java 获取操作系统级系统信息

Java 获取操作系统级系统信息,java,memory,resources,system,Java,Memory,Resources,System,我目前正在构建一个Java应用程序,它可以运行在许多不同的平台上,但主要是Solaris、Linux和Windows的变体 ProcessorInfo info = HardwareInfo.getProcessorInfo(); //Get named info System.out.println("Cache size: " + info.getCacheSize()); System.out.println("Family: " + info.getFamily());

我目前正在构建一个Java应用程序,它可以运行在许多不同的平台上,但主要是Solaris、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());
//[...]
是否有人能够成功提取底层操作系统中使用的当前磁盘空间、CPU利用率和内存等信息?那么Java应用程序本身在消费什么呢


我更希望在不使用JNI的情况下获得这些信息。

我认为最好的方法是实现。它适用于大多数主要的操作系统(几乎任何现代的操作系统),并且非常容易使用。开发者在他们的论坛和邮件列表上反应非常积极。我也喜欢它是GPL2。它们还提供了大量Java示例


您可以从运行时类获得一些有限的内存信息。这确实不是你想要的,但我想我会提供它的完整性。这里有一个小例子。编辑:您还可以从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());
    }
  }
}

看看包中提供的API。例如:


  • OperatingSystemMXBean.getSystemLoadAverage()

  • ThreadMXBean.getCurrentThreadCpuTime()
  • ThreadMXBean.getCurrentThreadUserTime()
还有很多其他有用的东西在里面。

这个包确实给了你比运行时多得多的信息——例如,它会给你堆内存(
ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()
)与非堆内存(
ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage()

您还可以获得进程CPU使用率(无需编写自己的JNI代码),但需要将
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();
        }
    }
}

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

通常,要获取低级操作系统信息,您可以调用特定于操作系统的命令,这些命令为您提供运行时.exec()所需的信息或者在Linux中读取诸如/proc/*之类的文件。

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

例如,我有一个网络密集型java进程——它是唯一运行的东西,CPU占99%,但其中只有55%被报告为“处理器CPU”

甚至不要让我从“平均负载”开始,因为它几乎毫无用处,尽管它是MXbean上唯一与cpu相关的项目。如果太阳在他们偶尔的智慧中暴露出像“GetTotalCompute”这样的东西


对于严肃的CPU监控,Matt提到的SIGAR似乎是最好的选择。

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


如果您使用的是Jrockit虚拟机,那么下面是获取虚拟机CPU使用率的另一种方法。运行时bean还可以为每个处理器提供CPU负载。我只在Red Hat Linux上使用过它来观察Tomcat的性能。您必须在catalina.sh中启用JMX remote才能工作

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");

通过使用
system.getenv()
,将相关环境变量名作为参数传递,可以获得一些系统级信息。例如,在Windows上:

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

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

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

它是一个简单的库,使用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());
//[...]

通过maven添加OSHI依赖项:

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

对于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();

以下是详细信息。

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

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

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

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

来获得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));
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);

OperatingSystemMXBean.getSystemLoadAverage()未在windows中实现,因为ThreadMXBean“太贵了”。getCurrentThreadCpuTime()只返回该线程已运行的时间。不是cpu使用率百分比。要将其编译,请将强制转换
OperatingSystemMXBean
替换为
com.sun.management.OperatingSystemMXBean
,并将
getOperatingSystemMXBean()
的所有实例置于
ManagementFactory.
之前。您需要适当地导入所有类。我得到的cpu使用率为0。我将cpu使用率公式更改为cpuUsage=processCpuTime/systemTime。我得到了一个我不理解的cpu使用率值。1.0作为
getCpuUsage
的结果是否意味着系统正在以100%的速度使用所有可用的处理器?正如@Raj所说,我总是得到0。。。您能举一个如何使用该代码的示例吗?请尝试
((double)(processCpuTime-lastprocescputime))/((double)(systemTime-lastSystemTime))
没有任何本机库可能会误导您。该项目使用本机库