我试着看看-Xmx
和-Xms
参数如何影响我的程序,并检查我的进程消耗了多少内存。
我写了一个简单的程序,但我无法推断出结果。请帮助。
public static void main( String[] args ) {
char[] array = new char[69926904];
}
我使用参数 -Xms5M -Xmx200M
运行。理想情况下,由于字符占用2个字节,因此在超出内存限制之前应保留100M字符。即使我们说,很少有空间用于指针和长度,我也不知道为什么它会在 之后抛出错误69926904 长度。
感谢。
答案 0 :(得分:26)
仔细阅读关于分代堆的JVM Garbage Collection Tuning Guide,希望能回答你的问题。
使用-XX:+PrintGCDetails
选项运行Java,一切都应该变得清晰:
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,这正是char[69926904]
的大小(16字节标题+ 2 * 69926904字节的数据)。
答案 1 :(得分:11)
此信息来自Tuning Garbage Collection with the 5.0 Java[tm] Virtual Machine上的Oracles页面。
首先了解堆的工作原理非常重要。您可能知道对象(如您的数组)存储在堆中。但是,堆不是一个统一的空间。它实际上分为三代,即 Young , Tenured 和 Permanent 代。
当生成填满时,每一代都会发生垃圾收集。物体首先分配给年轻一代,并且由于婴儿死亡,大多数物体死在那里。一些幸存的物体被移动到终身一代。当需要收集终生代时,有一个主要的集合往往要慢得多,因为它涉及所有活动对象。
"年轻一代由伊甸园和两个幸存者空间组成。 对象最初在eden中分配。一个幸存者空间是空的 在任何时候,并作为下一个目的地,复制 收集伊甸园和其他幸存者空间中的任何活物。 以这种方式在幸存者空间之间复制对象,直到它们为止 年龄足够终身,或复制到终身一代。"
"与终身一代密切相关的第三代人是 永久的一代。永久的一代是特殊的,因为它 保存虚拟机描述的对象所需的数据 在Java语言级别没有等价。例如 描述类和方法的对象存储在永久物中 。一代"
除了控制总堆大小的-Xms
和-Xmx
参数外,还有控制各个段大小的参数。在您的示例中,您设置的是最大总堆大小,但您仍在使用默认生成比率。
"默认情况下,年轻代的大小由NewRatio控制。对于 例如,设置-XX:NewRatio = 3意味着年轻人之间的比例 和终身一代是1:3。换句话说,组合的大小 伊甸园和幸存者空间将占总堆的四分之一 大小"
"在理想的次要集合中,活动对象从一个集合中复制 年轻一代的一部分(伊甸园空间加上第一个幸存者) 空间)到年轻一代的另一部分(第二个幸存者 空间)。但是,无法保证所有活动对象都会 适合第二个幸存者空间。确保未成年人 即使所有对象都是实时的,也可以完全免费收集 必须在终身代中保留记忆以容纳所有人 活物。在最坏的情况下,这个保留的内存等于 伊甸园的大小加上非空幸存者空间中的物体。什么时候 为此,终身代人没有足够的内存可用 最糟糕的情况是,会发生一个主要的收藏。
你要做的就是存放一个巨大的物体。这个对象必须适合其中一代,并且根本没有足够大的代。即使堆的总大小大于对象,也没有用,因为对象不能跨越多代。
尝试在运行代码时添加以下参数:-XX:NewRatio=10
。如上所述,这将使终身产生十倍于年轻一代。结果,一个更大的对象将能够适应终身一代。
另一种解决方案是简单地避免使用大量的物体。没有一个大型阵列,而是有几个较小的阵列。