当前位置: 首页 > 知识库问答 >
问题:

为什么do-xmx和runtime.maxmemory不一致

锺离德运
2023-03-14

添加时

 -Xmx????m

对于命令行,JVM会给出一个接近于该值的堆,但最多可以超出14%。JVM可以给出一个更接近您所想要的数字,但只能通过反复试验。

 System.out.println(Runtime.getRuntime().maxMemory());
-Xmx1000m ->  932184064
-Xmx1024m -Xmx1g ->  954728448
-Xmx1072m ->  999292928
-Xmx1073m -> 1001390080

显然,堆可以是1000000000上面的东西,但为什么这个-xmx1073m而不是-xmx1000m呢?

BTW1G==1024M表示1G应为1024^3,比1000^3高7%,但您得到的值比1000^3低7%。

偏离了这么多,表明我缺少了关于堆工作方式的一些基本知识。如果我请求-xmx1000m,而它是1001390080我不会在意,我会假设它需要遵守某些分配倍数,但是给您932184064意味着堆比我想象的要复杂。

编辑我发现

-Xmx1152m gives 1073741824 which is exactly 1024^3

因此,在本例中,maxMemory()比我要求的少了128 MB。

顺便说一下128是我最喜欢的数字。我今天在街号128的一个会议上,演讲者引用了128页的一本书

共有1个答案

段干开宇
2023-03-14

这种差异似乎是由垃圾回收器的生存空间大小造成的。

如文档中所述,-xmx标志控制内存分配池的最大大小。内存分配池的堆部分分为Eden、Survivor和Tenured空间。如本答案所述,存在两个幸存者区域,其中只有一个区域可用于在任何给定时间点保存活动对象。因此,runtime.maxmemory()报告的可用于分配对象的总表观空间必须从总堆内存池中减去一个幸存者空间的大小。

您可以使用MemoryMXBeanMemoryPoolMXBean类获得关于内存分配的更多信息。下面是我编写的一个简单程序:

import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryPoolMXBean;

public class MemTest {
  static String mb (long s) {
    return String.format("%d (%.2f M)", s, (double)s / (1024 * 1024));
  }

  public static void main(String[] args) {
    System.out.println("Runtime max: " + mb(Runtime.getRuntime().maxMemory()));
    MemoryMXBean m = ManagementFactory.getMemoryMXBean();

    System.out.println("Non-heap: " + mb(m.getNonHeapMemoryUsage().getMax()));
    System.out.println("Heap: " + mb(m.getHeapMemoryUsage().getMax()));

    for (MemoryPoolMXBean mp : ManagementFactory.getMemoryPoolMXBeans()) {
      System.out.println("Pool: " + mp.getName() + 
                         " (type " + mp.getType() + ")" +
                         " = " + mb(mp.getUsage().getMax()));
    }
  }
}
Runtime max: 1037959168 (989.88 M)
Non-heap: 224395264 (214.00 M)
Heap: 1037959168 (989.88 M)
Pool: Code Cache (type Non-heap memory) = 50331648 (48.00 M)
Pool: Eden Space (type Heap memory) = 286326784 (273.06 M)
Pool: Survivor Space (type Heap memory) = 35782656 (34.13 M)
Pool: Tenured Gen (type Heap memory) = 715849728 (682.69 M)
Pool: Perm Gen (type Non-heap memory) = 174063616 (166.00 M)

注意,Eden+2*survivor+Tenured=1024m,这正好是命令行上请求的堆空间量。非常感谢“荒诞思维”指出了这一点。

您在不同JVM之间观察到的差异可能是由于选择不同世代的默认相对大小的不同启发式。如本文所述(适用于Java 6,找不到最新的),您可以使用-xx:newRatio-xx:survivorratio标志显式控制这些设置。因此,运行以下命令:

java -Xmx1024m -XX:NewRatio=3 -XX:SurvivorRatio=6

您告诉JVM:

Young:Tenured = (Eden + 2*Survivor):Tenured = 1:3 = 256m:768m
Survivor:Eden = 1:6 = 32m:192m

因此,使用这些参数,请求的-xmx值与runtime.maxMemory()报告的可用内存之间的差值应该是32M,这是使用上述程序验证的。现在,您应该能够准确预测runtime报告的给定命令行参数集的可用内存,这是您真正想要的,对吗?

 类似资料:
  • 问题内容: 当您添加 在命令行中,JVM给您提供了一个接近此值的堆,但最多可以出14%。JVM可以使您更接近所需的数字,但只能通过反复试验才能实现。 版画 我正在运行HotSpot Java 8 Update 5。 显然,堆可以在上面,但是为什么要这样而不是说呢? BTW == 表示应该为1024 ^ 3,比1000 ^ 3高7%,但您得到的东西比1000 ^ 3低7%。 太多的变化表明我缺少关于

  • 问题内容: 我期望Runtime.maxMemory()完全返回-Xmx,但是它返回一个较低的值。那么它返回什么呢? 问题答案: -Xmx标志的解释取决于VM。包括HotSpot在内的某些VM会对该选项的有效值施加下限。CCC提案不应以这种方式提及-Xmx标志。 参考

  • 本文向大家介绍do……while和while……do有什么区别?相关面试题,主要包含被问及do……while和while……do有什么区别?时的应答技巧和注意事项,需要的朋友参考一下 前一个循环一遍再判断,后一个判断以后 再循环。    

  • 问题内容: 我运行以下方法Runtime.getRuntime()。maxMemory()并给出了85196800。 但是,然后我从命令行运行了top,它显示了 那不是显示使用了156M的内存吗?有什么想法吗? 问题答案: 从文档中 maxMemory()-返回Java虚拟机将尝试使用的最大内存量。 顶部仅显示系统已分配给该进程的(虚拟)内存量-您在询问Java在最坏的情况下可以尝试使用多少内存。

  • JVM选项: 正如预期的那样,JVM将为JVM堆分配将近20MB的内存。 但请参阅以下 GC 详细信息: PSYoungGen总计9216K,已用4612k[0x 00000000 ff 6000000,0x 0000000010000000100000000]< br > Eden空间8192K,56%已用[0x 000000000 ff 600000,0x 0000000 FFA 812d 8

  • 问题内容: 什么意思 问题答案: 指定内存分配池的最大大小(以字节为单位)。此值必须是大于2 MB的1024的倍数。追加字母k或K表示千字节,或者追加m或M表示兆字节。默认值为64MB。在Solaris 7和Solaris 8 SPARC平台上,此值的上限约为4000m,在Solaris 2.6和x86平台上,该值的上限约为2000m(减去开销)。例子: 因此,简单来说,就是将Java堆内存从可用