2008-09-16 67 views
1

我在HP-UX环境中遇到了某些Java应用程序的特殊问题。在HP-UX环境JVM中,C堆中运行的是Java堆吗?

堆被设置为-mx512,然而,使用gpm查看此java进程的内存区域时,它显示它使用了高达1.6GB的RSS内存,并将1.1GB分配给DATA区域。在24-48小时内增长非常迅速,然后大幅减速,每隔几小时仍然增长2MB。但是,Java堆没有泄露的迹象。

好奇如何这是可能我研究了一下,发现内存泄漏在Java堆和c堆这款惠普写了:http://docs.hp.com/en/JAVAPERFTUNE/Memory-Management.pdf

我的问题是什么决定了在C堆VS java的运行堆,以及不通过java堆的东西,你将如何识别在C堆上运行的那些对象?此外,java堆是否位于C堆内部?

回答

0

我唯一的猜测是你给出的数字是Java VM中的内存泄漏。您可能想要尝试其中列出的其他虚拟机中的一个虚拟机。另一个(更困难的)选择可能是在HP平台上编译开放的Java。 Sun公司的Java尚未百分百开放,他们正在研究它,但我相信SourceForge中有一个是。

爪哇也顺便闪过记忆。有时候它会混淆操作系统内存管理(你会发现当Windows耗尽内存并要求Java释放某些东西时,Java会触及它的所有对象,导致它们从交换文件中加载,窗口尖叫在痛苦中死亡),但是我不认为这就是你所看到的。

2

通常,只有Java对象中的数据存储在Java堆中,Java VM所需的所有其他内存都是从“本机”或“C”堆中分配的(实际上,Java堆本身就是从C堆分配的一个连续块)。

由于JVM需要Java堆(如果正在使用分代垃圾收集时使用堆)才能成为连续的内存块,因此通常在JVM启动时分配整个最大堆大小(-mx值)。在实践中,Java VM会尝试最小化它对这个空间的使用,这样操作系统就不需要为它保留任何实际的内存(操作系统足够了解一段存储从未被写入) 。

因此,Java堆将占用一定量的内存空间。

剩余的存储空间将被Java VM和任何正在使用的JNI代码使用。例如,JVM需要内存来存储来自加载类的Java字节码和常量池,JIT编译代码的结果,用于编译JIT代码的工作区域,本地线程堆栈和其他此类杂项。

JNI代码只是特定于平台的(编译的)C代码,可以以“本地”方法的形式绑定到Java对象。当这个方法被执行时,绑定代码被执行并且可以使用标准C例程(例如malloc)分配内存,这将消耗C堆上的内存。

4

考虑构成Java过程的是什么。

您有:

  • 的JVM(一个C程序)
  • JNI数据
  • Java字节码
  • Java数据

值得注意的是,他们都住在C堆(JVM堆自然是C堆的一部分)。

在Java堆是简单地JAVA字节代码和Java数据。但Java堆中还有什么是“自由空间”。

典型的(即Sun)JVM只根据需要增长Java堆,但永远不会缩小它。一旦达到其定义的最大值(-Xmx512M),它会停止增长并处理剩下的任何事情。当这个最大堆耗尽时,你会得到OutOfMemory异常。

什么是Xmx512M选项不这样做,是限制进程的总体规模。它仅限制进程的Java堆部分。例如,您可能有一个人为的Java程序,它使用10MB的Java堆,但调用分配500MB C堆的JNI调用。即使Java堆很小,您也可以看到您的进程大小如何。另外,使用新的NIO库,您还可以在堆外部附加内存。

,你必须考虑的另一个方面是,Java的GC是典型的“复制收集器”。这意味着需要从内存中收集“实时”数据,并将其复制到另一部分内存中。这个空的空间复制到IS NOT PART OF HEAP,至少不是Xmx参数。它就像“新堆”一样,并且在副本之后成为堆的一部分(旧空间用于下一个GC)。如果你有一个512MB的堆,而且它的容量是510MB,那么Java将会把实时数据复制到某个地方。天真的想法是到另一个大的开放空间(如500 + MB)。如果你的所有数据都是“活的”,那么它需要一个大块来复制。

因此,您可以看到,在最极端的情况下,您至少需要将系统上的可用内存翻倍以处理特定的堆大小。 512MB堆至少1GB。

原来,实际情况并非如此,内存分配等比这更复杂,但您确实需要大量的可用内存来处理堆副本,并且这会影响整个进程大小。

最后,请注意JVM执行有趣的事情,如在rt.jar类中映射到VM以简化启动。它们映射在只读块中,并可以在其他Java进程中共享。这些共享页面将对所有Java进程进行“计数”,即使它实际上只消耗一次物理内存(虚拟内存的魔力)。

现在至于为什么你的进程继续增长,如果你从未击中Java OOM消息,那意味着你的泄漏不在Java堆中,但这并不意味着它可能不在其他东西中JRE运行时,第三方JNI库,本地JDBC驱动程序等)。