如何在Java中查找物理内存大小?

20
我正在编写一个安装程序,用于针对将要运行的特定硬件调整产品配置。 特别是,我想确定系统中安装了多少物理内存,以便在产品运行时估计需要分配多少内存。
理想情况下,我希望能以平台无关、纯Java方式实现,因为该安装程序需要在几个不同的平台上运行,但如果这不可能,那么Windows解决方案更受欢迎,因为它是最常见的部署平台。
在这种情况下,可以安全地假设该产品将是盒子上唯一/主要运行的应用程序,因此我不必担心挤压其他人。 我不想过度分配,因为根据我们的经验,这可能会影响性能。

如果您的安装程序是Java编写的,它只有在JRE已经被安装的情况下才能正常工作... - Nate
谢谢 - 在这种情况下,JRE是软件的列出要求之一,因此我们可以假设它已经存在 :) - Martin McNulty
7个回答

23
您可以使用以下Java代码来查询物理内存:
com.sun.management.OperatingSystemMXBean os = (com.sun.management.OperatingSystemMXBean)
     java.lang.management.ManagementFactory.getOperatingSystemMXBean();
long physicalMemorySize = os.getTotalPhysicalMemorySize();

但是包com.sun.management是可选的,不需要在每个平台上都可用。


1
在我看来,这绝对是最好的答案。它可以在Linux和Windows上工作,而且在Windows上不需要使用WMI进行特殊处理... - gilad hoch
2
请注意,当使用32位JVM时,此操作将永远不会返回超过4GB的数据。 - Michael Berry
谢谢,很好。这正是我需要的。我打算创建一个C++解决方案,并从我的Java程序中调用它。 - Yan Khonski

6

本地JMX和MBeans怎么样?试试这个:

MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
Object attribute = mBeanServer.getAttribute(new ObjectName("java.lang","type","OperatingSystem"), "TotalPhysicalMemorySize");
System.out.println("Total memory: "+ attribute.toString() +" B");

你可以通过这种方式访问许多有用的信息。

我真的很喜欢这个答案,简短而正确。没有内部JDK/JRE引用(com.sun.management ...)。谢谢!;-) - jazz64

4
如果您的目的是调整JVM的内存设置以使用所有可用的物理内存,但不超过它,那么您可以查看-XX:+ AggressiveHeap参数。有了它,您不需要知道可用内存。JVM将自动缩放其参数。

4
import java.lang.management.ManagementFactory;

import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;

public class Main {
  public static void main(String[] args) throws InstanceNotFoundException, AttributeNotFoundException, MalformedObjectNameException, ReflectionException, MBeanException  {
  /* Total number of processors or cores available to the JVM */


      MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
      Object attribute = mBeanServer.getAttribute(new ObjectName("java.lang","type","OperatingSystem"), "TotalPhysicalMemorySize");
      Object attribute2 = mBeanServer.getAttribute(new ObjectName("java.lang","type","OperatingSystem"), "FreePhysicalMemorySize");
      System.out.println("Total memory: "+ Long.parseLong(attribute.toString()) / 1024  +"MB");
      System.out.println("Free  memory: "+ Long.parseLong(attribute2.toString()) / 1024  +"MB");    

 }
}

2

如果你使用的是Windows系统,你需要访问WMI - 这将帮助你快速入门: 从Java访问Windows管理工具(WMI).

你需要使用WMI中的Win32_LogicalMemoryConfiguration部分。

可能存在一种使用纯java的方法,但我不知道。


谢谢!看起来这个类在XP和Server 2003中不受支持,在Vista及以后版本中也不可用(http://msdn.microsoft.com/en-us/library/aa394181(VS.85).aspx)。显然,Win32_OperatingSystem是它的替代品。 - Martin McNulty
是的,不同版本的Windows支持不同的WMI类。您需要根据目标操作系统进行调整。 - Nate

1
在Linux下,您可以使用sysinfo(2)。我认为从纯Java实现这个功能是不可能的。

干杯 - 我应该通过JNI调用它吗? - Martin McNulty
是的,那就是C系统调用。你可以从命令行解析free(1)的结果,我相信还有更好的方法,但现在想不出来了。你也可以把所有这些放在一个shell脚本或包中,让用户用来安装你的应用程序,而不是使用jni。 - wds

1
我过去几年遇到过这个问题多次。现有答案大多是针对特定平台的黑客方法,因此,今天JAVA没有任何自包含、平台无关的工具集?
实际上,有一个:https://github.com/oshi/oshi
OSHI是一个免费的基于JNA(本地)操作系统和硬件信息库,用于Java。它不需要安装任何其他本地库,并旨在提供跨平台实现,以检索系统信息,如操作系统版本、进程、内存和CPU使用情况、磁盘和分区、设备、传感器等。
是的,它确实在内部使用JNI,就像其他方法一样,但如果所有细节都被仔细隐藏在干净的API和包后面,并且如果您正在使用任何体面的现代依赖管理工具(maven、gradle等),那么安装也相当容易。
对于任何严肃的项目,请使用此工具。不要重复造轮子。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接