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

Java进程内存检查测试

欧博简
2023-03-14

我试图了解-Xmx-Xmsparameters对我的程序的影响,并检查我的进程消耗了多少内存。

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

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

我用参数< code>-Xms5M -Xmx200M运行。理想情况下,由于一个字符占用2个字节,在超过内存限制之前,它应该容纳100M个字符。即使我们说,很少的空间用于指针和长度,我不知道,为什么它在69926904长度后抛出错误。

谢谢。

共有2个答案

傅新
2023-03-14

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

首先,了解堆是如何工作的很重要。您可能知道对象(比如您的数组)存储在堆中。然而,堆并不是一个统一的空间。它实际上分为三代,即青年、终身和永久一代。

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

“年轻一代由伊甸园和两个幸存者空间组成。对象最初是在eden中分配的。一个幸存者空间在任何时候都是空的,并作为下一个的目的地,复制收集伊甸园和其他幸存者空间中的任何活对象。对象以这种方式在幸存者空间之间复制,直到它们老到足以保留,或者复制到保留世代。”

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

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

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

“在一个理想的次要集合中,活的对象从年轻一代的一部分(伊甸园空间加上第一个幸存者空间)复制到年轻一代中的另一部分(第二个幸存者空间然而,不能保证所有活的物体都能放入第二个幸存者空间。为了确保即使所有对象都是活动的,也可以完成次要集合,必须在永久生成中保留足够的可用内存,以容纳所有活动对象。在最坏的情况下,这个保留内存等于eden的大小加上非空幸存者空间中的对象。如果在这种最坏的情况下,终身制代中没有足够的可用内存,则会发生一次大型收集。

你要做的是存储一个巨大的对象。这个对象必须适合其中的一个世代,而且没有足够大的世代。即使堆的总大小比对象大,这也无济于事,因为对象不能跨越多个世代。

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

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

宋勇
2023-03-14

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

使用< code>-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)

您的 2 亿个 Java 堆由 2 代组成:1/3 (66.7M) 是年轻基因,2/3 (133.3M) 是旧代。

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

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

 类似资料:
  • 问题内容: 我想看看和我的程序参数的影响,并检查多少内存我的过程中消耗。 我编写了一个简单的程序,但无法推断出结果。请帮助。 我跑了参数 。理想情况下,由于一个字符占用2个字节,因此在超过内存限制之前,它应容纳100M个字符。即使我们说,几乎没有空间用于 指针 和 length ,我也不知道,为什么它在 69926904 length 之后会 引发 错误 。 谢谢。 问题答案: 仔细阅读有关Gen

  • used_memory:859192数据结构的空间 used_memory_rss:7634944实占空间 mem_fragmentation_ratio:8.89前2者的比例,1.N为佳,如果此值过大,说明redis的内存的碎片化严重,可以导出再导入一次.

  • 问题内容: 如果我具有流程的PID,则os.FindProcess是否足以测试该流程的存在?我的意思是,如果返回,我是否可以认为它已终止(或被杀死)? 编辑: 我刚刚写了一个包装函数(旧式bash流程测试)。这可以正常工作,但是如果有其他解决方案(使用go库完成),我仍然很高兴。 问题答案: 这是查看进程是否处于活动状态的传统的Unix方式-向其发送0信号(就像您对bash示例所做的一样)。 来自

  • script/下的memstat.sh或者ps_mem.py都可以查看系统的内存情况,两个工具都需要root权限。

  • 我是java内存问题的新手,在调试java进程的内存使用时遇到了问题,需要你的帮助。根据“the java进程占用8G常驻内存和9.4G虚拟内存。这对于这个进程来说太多了,我想检查一下为什么它会吃掉内存。所以我使用jmap进行了一次堆转储(没有使用‘live’选项,因为它可能会触发GC ),发现只有100MB的活动对象,还有1.5G的不可达对象。那么剩下的6G内存去哪了?我应该检查哪些其他类型的非

  • #!/bin/bash # Get current swap usage for all running processes # Erik Ljungstrom 27/05/2011 # Modified by Mikko Rantalainen 2012-08-09 # Pipe the output to "sort -nk3" to get sorted output # Modified