Java 进程内存检查测试

2022-09-03 04:10:54

我试图查看和参数如何影响我的程序,并检查我的进程消耗了多少内存。-Xmx-Xms

我写了一个简单的程序,但无法推理出结果。请帮忙。

public static void main( String[] args ) {
        char[] array = new char[69926904];
}

我用参数-Xms5M-Xmx200M运行。理想情况下,由于一个字符需要 2 个字节,因此在超过内存限制之前,它应该包含 100M 个字符。即使我们说,很少有空间用于指针长度,我也不知道,为什么它会在69926904长度之后抛出错误。

谢谢。


答案 1

仔细阅读有关代堆的 JVM 垃圾回收调优指南,希望它能回答您的问题。

使用选项运行Java,一切都应该变得清晰:-XX:+PrintGCDetails

Heap
 PSYoungGen      total 3584K, used 294K [0x00000000fbd60000, 0x00000000fc160000, 0x0000000100000000)
  eden space 3072K, 9% used [0x00000000fbd60000,0x00000000fbda9860,0x00000000fc060000)
  from space 512K, 0% used [0x00000000fc0e0000,0x00000000fc0e0000,0x00000000fc160000)
  to   space 512K, 0% used [0x00000000fc060000,0x00000000fc060000,0x00000000fc0e0000)
 PSOldGen        total 136576K, used 136576K [0x00000000f3800000, 0x00000000fbd60000, 0x00000000fbd60000)
  object space 136576K, 100% used [0x00000000f3800000,0x00000000fbd60000,0x00000000fbd60000)
 PSPermGen       total 21248K, used 2595K [0x00000000ee600000, 0x00000000efac0000, 0x00000000f3800000)
  object space 21248K, 12% used [0x00000000ee600000,0x00000000ee888db0,0x00000000efac0000)

您的 200M Java 堆由 2 代组成:1/3 (66.7M) 是 YoungGen,2/3 (133.3M) 是 OldGen。

-XX:NewRatio选项允许更改比例,但默认值 2 意味着 YoungGen 将保留堆的 1/(2+1) 部分。

Java 对象不能跨越几代,因此对象的最大大小不能大于最大的一代。在你的例子中,最大的一代是OldGen:136576K = 139853824这正好是(16字节头+ 2 * 69926904字节数据)的大小。char[69926904]


答案 2

此信息来自 Oracles 关于使用 5.0 Java[tm] 虚拟机调整垃圾回收的页面。

堆和几代人

首先,重要的是要知道堆是如何工作的。如您所知,对象(如数组)存储在堆中。但是,堆不是一个统一的空间。它实际上分为三代,即年轻人终身和永久一代。

垃圾回收在每一代中发生,当这一代填满时。对象首先在年轻一代中分配,并且由于婴儿死亡率,大多数对象都在那里死亡。一些幸存的物品被转移到终身世代。当需要收集终身一代时,有一个主要集合通常要慢得多,因为它涉及所有活动对象。

“年轻一代由伊甸园和两个幸存者空间组成。对象最初在 eden 中分配。一个幸存者空间在任何时候都是空的,并作为下一个的目的地,复制伊甸园和另一个幸存者空间中的任何活物的集合。对象以这种方式在幸存者空间之间复制,直到它们足够大,可以被终身使用,或者被复制到终身一代。

“与终身一代密切相关的第三代是永久一代。永久生成是特殊的,因为它保存虚拟机所需的数据,以描述在 Java 语言级别上不具有等效性的对象。例如,描述类和方法的对象存储在永久生成中。

部分参数

除了 控制总堆大小的 参数之外,还有一些参数控制各个段的大小。在您的示例中,您正在设置最大总堆大小,但仍在使用默认生成比率。-Xms-Xmx

“默认情况下,年轻一代的规模由NewRatio控制。例如,设置 -XX:NewRatio=3 意味着年轻一代和终身制一代之间的比例为 1:3。换句话说,伊甸园和幸存者空间的总大小将是总堆大小的四分之一。

问题

“在理想的次要收藏中,活体物品从年轻一代的一部分(伊甸园空间加第一个幸存者空间)复制到年轻一代的另一部分(第二个幸存者空间)。但是,不能保证所有活体都适合第二个幸存者空间。若要确保即使所有对象都处于活动状态,次要集合也可以完成,必须在永久生成中保留足够的可用内存来容纳所有活动对象。在最坏的情况下,此保留内存等于伊甸园的大小加上非空的幸存者空间中的物体。当终身世代中没有足够的内存可用于这种最坏的情况时,将改为进行主要收集。

你试图做的是存储一个巨大的物体。这个物体必须适合其中一代,根本没有足够大的一代。即使堆的总大小大于对象,那也无济于事,因为对象不能跨越多代。

尝试的事项

尝试在运行代码时添加以下参数:。如上所述,这将使终身一代成为年轻一代的十倍。因此,一个更大的对象将能够适应终身一代。-XX:NewRatio=10

另一种解决方案是简单地避免使用如此巨大的物体。与其有一个巨大的阵列,不如有几个较小的阵列。