Java 6 Update 25 VM 崩溃:内存不足

Posted

技术标签:

【中文标题】Java 6 Update 25 VM 崩溃:内存不足【英文标题】:Java 6 Update 25 VM crash: insufficient memory 【发布时间】:2011-09-14 17:33:12 【问题描述】:

有关此问题的更新 - 见下文。

我遇到了一个(至少对我来说是可重现的)JVM 崩溃不是 OutOfMemoryError) (崩溃的应用程序是eclipse 3.6.2)。 但是,查看崩溃日志让我想知道:

#
# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (malloc) failed to allocate 65544 bytes for Chunk::new
# Possible reasons:
#   The system is out of physical RAM or swap space
#   In 32-bit mode, the process size limit was hit
# Possible solutions:
#   Reduce memory load on the system
#   Increase physical memory or swap space
#   Check if swap backing store is full
#   Use 64 bit Java on a 64 bit OS
#   Decrease Java heap size (-Xmx/-Xms)
#   Decrease number of Java threads
#   Decrease Java thread stack sizes (-Xss)
#   Set larger code cache with -XX:ReservedCodeCacheSize=
# This output file may be truncated or incomplete.

Current thread (0x531d6000):  JavaThread "C2 CompilerThread1" daemon 
[_thread_in_native, id=7812, stack(0x53af0000,0x53bf0000)]

Stack: [0x53af0000,0x53bf0000],  sp=0x53bee860,  free space=1018k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [jvm.dll+0x1484aa]
V  [jvm.dll+0x1434fc]
V  [jvm.dll+0x5e6fc]
V  [jvm.dll+0x5e993]
V  [jvm.dll+0x27a571]
V  [jvm.dll+0x258672]
V  [jvm.dll+0x25ed93]
V  [jvm.dll+0x260072]
V  [jvm.dll+0x24e59a]
V  [jvm.dll+0x47edd]
V  [jvm.dll+0x48a6f]
V  [jvm.dll+0x12dcd4]
V  [jvm.dll+0x155a0c]
C  [MSVCR71.dll+0xb381]
C  [kernel32.dll+0xb729]

我使用的是 Windows XP 32 位 SP3。我有 4GB 内存。 根据任务管理器,在启动应用程序之前,我有 2 GB 可用空间(+ 1 GB 系统缓存也可能被释放。)。我肯定有足够的空闲 RAM。

从开始到崩溃,我使用 visualvm 和 jconsole 记录了 JVM 内存统计信息。 我获取了直到崩溃前最后一刻的内存消耗统计信息。

统计显示以下分配的内存大小:

HeapSize:751 MB(使用 248 MB) 非堆大小(PermGen 和 CodeCache):150 MB(使用 95 MB) 内存管理区域的大小(Edenspace、Old-gen 等):350 MB 线程堆栈大小:17 MB(根据oracle 并且由于有 51 个线程正在运行)

我正在使用参数运行应用程序(jre 6 update 25,服务器 vm):

-XX:PermSize=128m
-XX:MaxPermSize=192m
-XX:ReservedCodeCacheSize=96m
-Xms500m
-Xmx1124m

问题:

当虚拟机和操作系统上的内存明显足够时,为什么 JVM 会崩溃? 通过上述设置,我认为我无法达到 2GB 32 位限制(1124MB+192MB+96MB+线程堆栈

谁能帮我弄清楚这里出了什么问题?

(注意:我最近从 Eclipse 3.4.2 升级到 Eclipse 3.6.2,从 Java 5 升级到 Java 6。我怀疑崩溃和这些更改之间存在联系,因为我以前没有见过这些)

更新

It seems to be a JVM bugJava 6 Update 25 中引入,与新的 jit 编译器有关。另见this blog entry. 根据博客,这个错误的修复应该是下一个 java 6 更新的一部分。 与此同时,我在崩溃期间获得了本机堆栈跟踪。我已经更新了上面的崩溃日志。

建议的解决方法,使用 VM 参数 -XX:-DoEscapeAnalysis 有效(至少它显着降低了崩溃的可能性)

【问题讨论】:

您可能将最大内存大小设置得太高,以至于 32 位空间无法支持。通常 JVM 会检测到这一点,但您可能会以无法检测到的方式接近极限。 如果你将PermSize增加到512m并添加-XX:PermSize=512m,是否还会出现错误? 这是哪个版本的 Java 6?描述类似于this bug ID,除了线程转储。 然后检查错误报告并尝试解决方法。或者使用 u23。 @Vineet 根据报告(这是重复的,也可以看看原始的错误报告)使用-XX:+DoEscapeAnalysis 时导致内存问题。但是,我不使用该选项。 【参考方案1】:

Windows 上 32 位 JVM 上的 2GB 不正确。 https://blogs.sap.com/2019/10/07/does-32-bit-or-64-bit-jvm-matter-anymore/

由于您使用的是 Windows-XP,因此您只能使用 32 位 JVM。

在 Windows 上的 32 位 VM 上,最大堆为 1.5GB。开始时您的内存为 1412MB,没有线程。您是否尝试减小交换堆栈大小 -Xss,是否尝试消除最初分配的 PermSize:-XX:PermSize=128m?听起来这是一个日食问题,而不是内存问题本身。

您可以迁移到不同机器上的更新 JVM 或不同(64 位)JVM 吗?即使您的目标是 windows-XP,也没有理由在其上开发,除非您必须这样做。 Eclipse 可以轻松地在远程机器上运行、调试和部署代码。

Eclipse 的 JVM 可以不同于您在 Eclipse 中运行或使用 Eclipse 运行的 JVM。 Eclipse 是一头记忆猪。您可以消除不必要的 eclipse 插件以使用更少的 eclipse 内存,它提供了您可能不需要或不想要的开箱即用的东西。

尝试清空引用(以消除循环不可回收的 GC 对象),重新使用分配的内存,使用单例,并分析您的内存使用情况以消除不必要的对象、引用和分配。其他提示:

首选静态内存分配,即每个 VM 分配一次,而不是 动态。 避免在函数中创建临时对象 - 考虑一个允许对象重用的 reset() 方法 避免字符串突变和自动装箱类型的突变。

【讨论】:

【参考方案2】:

我认为@ggb667 已经解决了您的 JVM 崩溃的原因。 32 位 Windows 架构限制将 Java 应用程序的可用 RAM 限制为 1.5GB1 ...而不是您推测的 2GB。此外,您忽略了包括可执行文件的代码段、共享库、本机堆和“其他东西”占用的地址空间。

基本上,这不是 JVM 错误。您只是在克服硬件和操作系统的限制。

在某些版本的 Windows 中存在一种可能的解决方案,即PAE (Physical Address Extension) 支持。根据该链接,带有 PAE 的 Windows XP 为用户进程提供了多达 4GB 的可用地址空间。但是,对于设备驱动程序支持有一些注意事项。

另一个可能的解决方案是减小最大堆大小,并做其他事情来降低应用程序的内存利用率;例如在 Eclipse 中减少工作区中“打开”项目的数量。

另见:Java maximum memory on Windows XP

1 - 不同来源对实际限制的说法不同,但明显小于 2GB。坦率地说,实际限制是多少并不重要。


在理想的世界里,这个问题应该不再对任何人有实际意义。 2020 年:

您不应该运行 Windows XP。自 2014 年 4 月以来,它已停止使用 您不应该运行 Java 6。自 2013 年 4 月以来,它已经结束了生命周期 如果您仍在运行 Java 6,那么您应该处于最后一个公共补丁版本:1.6.0_45。 (或者如果您有/曾经签订过支持合同,则可以在以后的 1.6 非公开版本中发布。)

无论哪种方式,您都不应该在该系统上运行 Eclipse。说真的,你可以花几百美元买一台新的 64 位机器,它有更多的内存等,这将使你能够运行最新的操作系统和最新的 Java 版本。您应该使用 that 来运行 Eclipse。

如果您确实需要在带有旧版本 Java 的旧 32 位机器上进行 Java 开发(因为您买不起新机器),建议您使用简单的文本编辑器和 Java 6 JDK命令行工具(以及第 3 方 Java 构建工具,如 Ant、Maven、Gradle)。

最后,如果您仍在尝试运行/维护停留在 Java 6 上的 Java 软件,那么您真的应该尝试摆脱这个漏洞。对你来说,生活只会变得更加艰难:

如果 Java 6 软件是内部开发的或者您有源代码,请移植它。 如果您依赖 Java 6 上的专有软件,请寻找新的供应商。 如果管理层拒绝,告诉他们他们可能需要“关闭”。

您/您的组织应该在七年前就处理过这个问题。

【讨论】:

【参考方案3】:

我在工作中偶然发现了一个类似的问题。我们为我们的应用程序设置了 -Xmx65536M ,但一直收到完全相同类型的错误。有趣的是,错误总是发生在我们的应用程序实际上进行相当轻量级计算的时候,相对而言,因此离这个限制还很远。

我们在网上找到了一个可能的解决方案:http://www.blogsoncloud.com/jsp/techSols/java-lang-OutOfMemoryError-unable-to-create-new-native-thread.jsp,它似乎解决了我们的问题。将 -Xmx 降低到 50G 后,我们没有遇到这些问题。

这个案子到底发生了什么我们还不清楚。

【讨论】:

【参考方案4】:

JVM 有它自己的限制,它会在它达到物理或虚拟内存限制之前很久就停止它。您需要调整的是堆大小,它与另一个 -X 标志一起使用。 (我认为这有点像 -XHeapSizeLimit 之类的创意,但我会检查一下。)

Here we go:

-Xmsn 指定内存分配池的初始大小,以字节为单位。 该值必须是 1024 的倍数 大于 1MB。附加字母 k 或 K 表示千字节,或 m 或 M 表示兆字节。默认 值为 2MB。例子:

   -Xms6291456
   -Xms6144k
   -Xms6m

-Xmxn 指定内存分配池的最大大小,以字节为单位。 该值必须是 1024 的倍数 大于 2MB。附加字母 k 或 K 表示千字节,或 m 或 M 表示兆字节。默认 值为 64MB。例子:

   -Xmx83886080
   -Xmx81920k
   -Xmx80m

【讨论】:

你的意思是 -Xmx ?这就是我在这里设置的。正如帖子中所述,我理论上无法达到该限制,即使我愿意,我也宁愿得到 OutOfMemoryError - 所以这不可能,恕我直言。 你不知道它不可能是这样的,因为你只是在查看最后一个样本你崩溃之前。看看这里oracle.com/technetwork/java/javase/tech/… 并尝试设置 -XX:-HeapDumpOnOutOfMemoryError 你也想看看 jmap oracle.com/technetwork/articles/javase/… @Charlie 我没有收到 OutOfMemoryError 因此您建议的选项无法触发。我遇到了 jvm 崩溃,这是不同的。 @MR 很高兴您知道出了什么问题。但是那你为什么要问呢?

以上是关于Java 6 Update 25 VM 崩溃:内存不足的主要内容,如果未能解决你的问题,请参考以下文章

Java VM:1.6.0_17 和 1.6.0_18 上的可重现 SIGSEGV,如何报告?

yun update更新后 vm-workstation 找不到kernel

Unity VM 崩溃(看起来像加速问题)

jdk1.6 VM调优实战

IOS Update 9 崩溃葫芦

我的代码使用超过 25GB 的内存和崩溃