Java进程内存检查测试

时间:2014-06-13 09:52:21

标签: java memory

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

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

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

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

感谢。

2 个答案:

答案 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。如上所述,这将使终身产生十倍于年轻一代。结果,一个更大的对象将能够适应终身一代。

另一种解决方案是简单地避免使用大量的物体。没有一个大型阵列,而是有几个较小的阵列。