Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在HP-UX环境JVM中,C堆和Java堆中运行的是什么?_Java_C_Jvm_Heap_Hp Ux - Fatal编程技术网

在HP-UX环境JVM中,C堆和Java堆中运行的是什么?

在HP-UX环境JVM中,C堆和Java堆中运行的是什么?,java,c,jvm,heap,hp-ux,Java,C,Jvm,Heap,Hp Ux,在HP-UX环境中的某些Java应用程序中,我遇到了一个特殊的问题 堆被设置为-mx512,但是,使用gpm查看这个java进程的内存区域,它显示它使用了超过1.6GBs的RSS内存,为数据区域分配了1.1GB。在24-48小时内快速增长,然后大幅放缓,仍然每几小时增长2MB。但是,Java堆没有泄漏的迹象 好奇这是怎么可能的,我研究了一下,发现HP在java堆和c堆中写了一篇关于内存泄漏的文章: 我的问题是什么决定了在C堆和java堆中运行什么,对于没有在java堆中运行的东西,您将如何识别在

在HP-UX环境中的某些Java应用程序中,我遇到了一个特殊的问题

堆被设置为-mx512,但是,使用gpm查看这个java进程的内存区域,它显示它使用了超过1.6GBs的RSS内存,为数据区域分配了1.1GB。在24-48小时内快速增长,然后大幅放缓,仍然每几小时增长2MB。但是,Java堆没有泄漏的迹象

好奇这是怎么可能的,我研究了一下,发现HP在java堆和c堆中写了一篇关于内存泄漏的文章:


我的问题是什么决定了在C堆和java堆中运行什么,对于没有在java堆中运行的东西,您将如何识别在C堆上运行的那些对象?此外,java堆是否位于C堆中?

根据您给出的数字,我唯一的猜测是java VM中存在内存泄漏。您可能想尝试您提到的论文中列出的其他虚拟机之一。另一个(困难得多)选择可能是在HP平台上编译开放式java

Sun的Java还不是100%开放的,他们正在开发它,但我相信sourceforge中有一个是这样的


顺便说一句,Java也会破坏内存。有时它会让操作系统的内存管理有点混乱(当windows内存不足并要求Java释放一些内存时,Java会接触到它的所有对象,导致它们从交换文件加载,windows会痛苦地尖叫并死去),但我不认为你看到的是这样的情况。

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

由于JVM要求Java堆(如果正在使用分代垃圾收集,则为堆)是一个连续的内存块,因此整个最大堆大小(-mx值)通常在JVM启动时分配。实际上,Java虚拟机会尽量减少对这个空间的使用,这样操作系统就不需要为它保留任何实际内存(操作系统很精明,知道什么时候一块存储从未写入)

因此,Java堆将在内存中占用一定的空间

其余的存储将由JavaVM和任何正在使用的JNI代码使用。例如,JVM需要内存来存储加载类中的Java字节码和常量池、JIT编译代码的结果、编译JIT代码的工作区、本机线程堆栈和其他类似的杂项


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

考虑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通常是一个“复制收集器”。这意味着它从正在收集的内存中获取“实时”数据,并将其复制到内存的不同部分。复制到的这个空空间不是堆的一部分,至少在Xmx参数方面不是。它类似于“新堆”,在复制之后成为堆的一部分(旧空间用于下一个GC)。如果你有一个512MB的堆,它是510MB,Java将把实时数据复制到某个地方。这种天真的想法是去另一个大的开放空间(比如500+MB)。如果您的所有数据都是“实时的”,那么它将需要一大块这样的数据才能复制到

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

事实证明,实际情况并非如此,内存分配等比这更复杂,但确实需要大量可用内存来处理堆拷贝,这会影响整个进程的大小

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

至于为什么您的进程会继续增长,如果您从未遇到Java OOM消息,这意味着您的泄漏不在Java堆中,但这并不意味着它可能不在其他地方(JRE运行时、第三方JNI库、本机JDBC驱动程序等)