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 bug 在 Java 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,如何报告?