Java 中显示物理内存大小的答案不正确

3

这是代码

import java.lang.management.ManagementFactory;

public class MemorySize {

   public static void main(String[] args){
    com.sun.management.OperatingSystemMXBean mxbean = 
    (com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
    System.out.println(mxbean.getTotalPhysicalMemorySize() + " Bytes "); 

上述代码给出的输出值为2147483647字节,相当于1.99 GB。但实际上已安装内存(RAM)为3.00GB(可用2.30GB)。如何获得正确的值,即2.30 GB。请帮忙。

这个程序是在32位的JVM上运行吗? - chrylis -cautiouslyoptimistic-
也许,我是说也许:JVM 可能不允许使用可用的整个 2.30 GB RAM,因此返回它被允许占用的最大 RAM。(仍然不确定...只是一种理论) :-) - Hungry Blue Dev
可能是 https://dev59.com/gG035IYBdhLWcg3wSN-r 的重复问题。 - Gundamaiah
这在我的64位JVM上运行良好。我怀疑这是32位地址空间的限制(可能是操作系统向JVM进程报告的)。 - chrylis -cautiouslyoptimistic-
1
@Ganesh 不是重复。 - Duncan Jones
3个回答

1
在Windows和Linux中,getTotalPhysicalMemorySize方法是通过向操作系统询问来实现的。在Linux的情况下,OpenJDK 11 JVM使用以下C代码完成此操作:
jlong num_avail_physical_pages = sysconf(_SC_AVPHYS_PAGES);
return (num_avail_physical_pages * page_size);

如果您查看sysconf(3)的手册页面,它会说到这个:

  • _SC_PHYS_PAGES:物理内存页数。

  • _SC_AVPHYS_PAGES:当前可用的物理内存页数。

另一份资料告诉我:

_SC_AVPHYS_PAGES返回的值是应用程序可以使用的内存量,而不会妨碍任何其他进程(假设没有其他进程增加其内存使用量)。

因此,您可以看到,这不是总物理RAM。相反,它是“可用”的物理RAM。

您也可以将上述内容解释为限制进程可能使用的RAM量的值。对于32位JVM,内存架构考虑将单个进程限制在远远小于4GB的地址空间。对于Windows,限制约为2GB。

(这是在Linux / OpenJDK 11上。我没有检查其他平台和版本。)

无论如何,该方法返回其返回值。据我所知,这是使用纯Java获得的最佳结果。
我该如何获得正确的值,即2.30克?
您可能需要使用System.exec(...)来运行一些特定于平台的实用程序,并从其输出中提取信息。或者实现一个本地方法,向操作系统提出不同的问题。
但是,您可能不应该使用所谓的“正确”值来调整JVM的大小。如果您尝试使用所有物理RAM,您可能会将操作系统推入危险的抖动行为。(您可能会唤醒可怕的oomkiller……然后选择错误的事物进行杀死!)

看起来这个问题在2013年之前就已经被修复了。来源:http://hg.openjdk.java.net/jdk/jdk11/file/1ddf9a99e4ad/src/jdk.management/unix/native/libmanagement_ext/OperatingSystemImpl.c#l372 - user1133275
我认为这个答案把getTotalPhysicalMemorySize和getFreePhysicalMemorySize的实现混淆了。getFreePhysicalMemorySize确实使用了_SC_AVPHYS_PAGES,但是getTotalPhysicalMemorySize一直使用_SC_PHYS_PAGES。正如其他评论中提到的,我怀疑这是使用32位JVM的限制。 - RyanR
是的。32位Java有额外的限制...取决于硬件架构和操作系统等因素。据我所知,没有主流的32位操作系统可以让您创建Java堆,可以使用所有概念上的32位地址空间,而不管可用的物理RAM数量。 - Stephen C

0
32位进程允许占用的最大内存通常仅为2GB。如果您使用64位JVM,则应该看到完整的大小。

0
你有检查过缓存的内存空间吗?如果是的话,那么 (com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean(); 并不能给你缓存所使用的空间。你可能需要尝试读取

/proc/meminfo 文件以获取正确的内存信息。


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