240

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

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

最好我想在不使用 JNI 的情况下获取这些信息。

4

16 回答 16

208

您可以从 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());
    }
  }
}
于 2008-08-25T02:53:21.287 回答
97

java.lang.management包确实为您提供了比运行时更多的信息——例如,它将为您提供ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()与非堆内存 () 分开的堆内存 ( ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage())。

您还可以获得进程 CPU 使用率(无需编写自己的 JNI 代码),但您需要java.lang.management.OperatingSystemMXBeancom.sun.management.OperatingSystemMXBean. 这适用于 Windows 和 Linux,我没有在其他地方测试过。

例如...更频繁地调用 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();
        }
    }
}
于 2008-09-14T23:41:21.307 回答
42

我认为最好的方法是通过 Hyperic 实现SIGAR API。它适用于大多数主要操作系统(接近任何现代操作系统)并且非常易于使用。开发人员对他们的论坛和邮件列表非常敏感。我也喜欢它是GPL2 Apache 许可的。他们也提供了大量的 Java 示例!

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

于 2008-08-25T02:36:04.963 回答
28

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

于 2010-06-23T01:17:33.383 回答
15

对于窗户,我是这样走的。

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

这是详细信息的链接

于 2016-06-30T15:05:43.470 回答
11

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

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

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

于 2012-08-16T14:31:14.223 回答
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));
}
于 2016-04-10T18:01:01.677 回答
6

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

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

里面还有很多其他有用的东西。

于 2008-08-26T07:09:20.493 回答
5

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

于 2009-03-24T19:43:26.730 回答
5

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 似乎是最好的选择。

于 2009-06-02T02:01:18.793 回答
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();
    }
}
于 2016-10-27T09:56:54.910 回答
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");
于 2011-11-10T07:55:07.970 回答
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());
//[...]
于 2016-03-02T21:24:01.123 回答
2

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

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

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

于 2019-04-24T14:44:03.080 回答
1

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

于 2009-03-24T12:32:46.750 回答
1

要在 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);
于 2020-01-01T11:18:46.683 回答