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

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

好奇如何做到这一点,我研究了一下,发现了有关HP在Java堆和C堆中的内存泄漏的文章: http : //docs.hp.com/en/JAVAPERFTUNE/Memory-Management.pdf

我的问题是什么决定C堆和Java堆中运行的内容,对于未通过Java堆运行的事物,您将如何识别正在C堆上运行的那些对象? 另外,java堆是否位于C堆内部?

===============>>#1 票数:4

考虑一下组成Java进程的东西。

你有:

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

值得注意的是,它们都生活在C堆中(JVM Heap自然是C堆的一部分)。

Java堆中只是Java字节码和Java数据。 但是Java堆中也有“可用空间”。

典型的(即Sun)JVM仅根据需要增加Java Heap,而不会缩小。 一旦达到定义的最大值(-Xmx512M),它将停止增长并处理剩余的内容。 当最大堆耗尽时,您将获得OutOfMemory异常。

Xmx512M选项不做的事情是限制进程的整体大小。 它仅限制了过程中的Java Heap部分。

例如,您可能有一个人为设计的Java程序,该程序使用10mb的Java堆,但是调用了分配500MB C堆的JNI调用。 即使Java堆很小,您也可以看到进程大小如何。 同样,使用新的NIO库,您也可以在堆外部附加内存。

您必须考虑的另一方面是Java GC通常是“ Copying Collector”。 这意味着它将从正在收集的内存中获取“实时”数据,并将其复制到内存的其他部分。 至少从Xmx参数而言,复制到的此空白空间不是堆的一部分。 就像“新堆”一样,在复制后成为堆的一部分(旧空间用于下一个GC)。 如果您有一个512MB的堆,而该堆的大小为510MB,则Java将在某个地方复制实时数据。 天真的想法是去另一个大的开放空间(例如500 + MB)。 如果您的所有数据都是“实时”的,那么将需要一大块复制到其中。

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

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

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

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

===============>>#2 票数: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堆上的内存。

===============>>#3 票数:0

我对给出的数字的唯一猜测是Java VM中的内存泄漏。 您可能要尝试在您引用的论文中列出的其他VM之一。 另一个(要困难得多)的替代方法可能是在HP平台上编译开放的Java。

Sun的Java尚未100%开放,他们正在开发它,但是我相信sourceforge中有一个。

Java也顺便破坏了内存。 有时,这会使操作系统的内存管理有些混乱(当Windows内存不足并要求Java释放一些内存时,您会看到它,Java触摸了所有对象,导致它们从交换文件中加载,Windows痛苦地尖叫着,死了)。我认为那不是您所看到的。

  ask by zxcv translate from so

未解决问题?本站智能推荐:

1回复

减少JVM中未使用的堆大小

这里和这里已经有类似的问题 ,但是JVM参数的改变都没有引出我同样的解决方案。 我只是想减少我的JVM未使用的堆大小,以便它更接近地反映实际使用情况(将其释放到操作系统)。 我一直在使用YourKit来分析内存使用情况,它通常如下所示: 我在Windows 7 64位,8 GB
2回复

如何确定JVM中每个堆代的大小?

如果我用-Xms256M和-Xmx512M启动我的JVM,在任何时候,我可以确定专门分配给堆的年轻和终身代的空间量吗?
1回复

javacore和heapdump中的堆大小:IBM JVM上相差20倍

注意到生产服务器(Websphere8.5.5)开始消耗大量内存。 javacore dump中的数字清楚地表明,罪魁祸首是一个不合时宜的堆: 但是同时,在MAT中打开的堆转储报告堆的总容量约为200M(有时高达300M,但从未超过此数量)。 到底是什么意思 堆转储值得信赖
1回复

运行Java是否每次都会创建一个新的JVM实例和一个新的堆?

每次在计算机上运行Java应用程序时,是否都在创建JVM实例? 如果是这样,我是否也为此JVM实例及其运行的Java应用程序获得了一个堆(具有我指定的大小)? 还是我的机器上运行Java应用程序的机器上有一个堆和一个JVM实例,并为其进程保留了堆空间? 如果这是真的,在指定要为每个应用
7回复

在运行时设置JVM堆大小

有没有办法从正在运行的Java程序中设置堆大小?
2回复

是否有用于实时查看JVM堆内存中对象变化的软件? [关闭]

假设您有一个正在运行的Java应用程序,并且想要检查按钮单击更改了哪些对象属性以及JVM堆内存中的何处。 在一个小程序中,您可以逐步调试单击,但是如果它是一个很大的程序,则可能要花费很多时间。 因此,有一个JVM监视器可以记录和显示此类事件后堆中的更改。 我知道我可以在事件发生之前和之后进
2回复

JVM堆大小问题

我刚刚开始研究JVM堆大小,并观察到一些奇怪的行为。 我的系统RAM大小为4 GB 操作系统是64位Windows 7 Java版本是1.7 这是观察结果: 我编写了一个示例主程序,该程序启动并立即进入等待状态。 当我使用-Xms1024m -Xmx
4回复

JVM抛出java.lang.OutOfMemoryError:堆空间(文件处理)

我编写了一个文件伪造处理器,该处理器可以获取每个文件的MD5哈希值,然后将其添加到哈希图中,然后将所有具有相同哈希值的文件都添加到一个名为dupeList的哈希图中。 但是,当运行大型目录进行扫描(例如C:\\ Program Files \\)时,它将引发以下错误 由于它可以处理许多
3回复

一般问题:Java具有堆和本地堆栈。你可以从堆中访问任何对象吗?

我真的在看传递值与Java如何分配对象之间的区别以及java将对象放在堆栈上的作用。 反正有没有访问堆上分配的对象? java强制执行哪些机制来保证正确的方法可以从堆中访问正​​确的数据? 看起来如果你是狡猾的,甚至可能在运行时操纵java字节码,你可能能够在不应该的时候从堆中操作
6回复

如何选择jvm堆大小?

我通常对jvm堆大小做的是将max值设置得非常高,以避免臭名昭着的OutOfMemoryException。 然而,这种策略(或缺乏策略)似乎并不是很聪明。 :-)。 我的问题是如何选择最小值和最大值,以及两者之间的差异(max-min应该小还是大?)。 例如,从这里 :