【发布时间】:2011-09-26 12:54:03
【问题描述】:
问题描述
在运行我的 Java 服务器应用程序一段时间后,我在 Solaris 上遇到了 Oracle Java 虚拟机的奇怪行为。通常,当 jvm 崩溃时,hs_err_pid.log 文件被创建(位置由-XX:ErrorFile jvm 参数确定,如下所述:How can I suppress the creation of the hs_err_pid file?
但在我的情况下,该文件没有创建,唯一剩下的是core核心转储文件。
使用pstack 和pflags 标准Solaris 工具,我能够从core 文件中收集有关崩溃的更多信息(包括在下面)。
尝试过的解决方案
-
尝试在文件系统中查找所有
hs_err_pid.log文件,但找不到任何东西(即使在应用程序工作目录之外)。即:find / -name "hs_err_pid*" 我试图查找与 jvm 相关的 jvm 错误,但我找不到与此案例类似的有趣内容。
- 问题看起来有点类似于:Java VM: reproducable SIGSEGV on both 1.6.0_17 and 1.6.0_18, how to report?,但我仍然无法确认这一点,因为缺少
hs_err_pid.log文件,当然操作系统平台也不同。 -
(编辑) 正如Tool for analyzing java core dump 问题的答案之一所建议的,我已经使用
jmap从core文件中提取了堆转储,并使用Eclipse MAT 对其进行了分析。我发现了一个泄漏(在核心转储 1,4 M 个元素时,添加到 HashMap 的元素永远不会被清理)。然而,这并不能解释为什么没有生成hs_err_pid.log文件,也没有解释 jvm 崩溃的原因。 -
(EDIT2) 正如 Darryl Miles 所建议的,已检查 -Xmx 限制(测试包含无限期将对象添加到
LinkedList的代码):-
java -Xmx1444m Test结果与java.lang.OutOfMemoryError: Java heap space, -
java -Xmx2048m Test结果与java.lang.OutOfMemoryError: Java heap space, -
java -Xmx3600m Test结果与核心转储。
-
问题
有没有人遇到过类似的 jvm 问题以及如何在这种情况下继续查找实际发生的情况(即在什么情况下核心从 jvm 转储并且没有创建 hs_err_pid.log 文件)?
任何解决此问题的提示或指针都会非常有帮助。
提取的标志
# pflags core
...
/2139095: flags = DETACH
sigmask = 0xfffffeff,0x0000ffff cursig = SIGSEGV
提取的堆栈
# pstack core
...
----------------- lwp# 2139095 / thread# 2139095 --------------------
fb208c3e ???????? (f25daee0, f25daec8, 74233960, 776e3caa, 74233998, 776e64f0)
fb20308d ???????? (0, 1, f25db030, f25daee0, f25daec8, 7423399c)
fb20308d ???????? (0, 0, 50, f25da798, f25daec8, f25daec8)
fb20308d ???????? (0, 0, 50, f25da798, 8561cbb8, f25da988)
fb203403 ???????? (f25da988, 74233a48, 787edef5, 74233a74, 787ee8a0, 0)
fb20308d ???????? (0, f25da988, 74233a78, 76e2facf, 74233aa0, 76e78f70)
fb203569 ???????? (f25da9b0, 8b5b400, 8975278, 1f80, fecd6000, 1)
fb200347 ???????? (74233af0, 74233d48, a, 76e2fae0, fb208f60, 74233c58)
fe6f4b0b __1cJJavaCallsLcall_helper6FpnJJavaValue_pnMmethodHandle_pnRJavaCallArguments_pnGThread__v_ (74233d44, 74233bc8, 74233c54, 8b5b400) + 1a3
fe6f4db3 __1cCosUos_exception_wrapper6FpFpnJJavaValue_pnMmethodHandle_pnRJavaCallArguments_pnGThread__v2468_v_ (fe6f4968, 74233d44, 74233bc8, 74233c54, 8b5b4
00) + 27
fe6f4deb __1cJJavaCallsEcall6FpnJJavaValue_nMmethodHandle_pnRJavaCallArguments_pnGThread__v_ (74233d44, 8975278, 74233c54, 8b5b400) + 2f
fe76826d __1cJJavaCallsMcall_virtual6FpnJJavaValue_nLKlassHandle_nMsymbolHandle_4pnRJavaCallArguments_pnGThread__v_ (74233d44, 897526c, fed2d464, fed2d6d0, 7
4233c54, 8b5b400) + c1
fe76f4fa __1cJJavaCallsMcall_virtual6FpnJJavaValue_nGHandle_nLKlassHandle_nMsymbolHandle_5pnGThread__v_ (74233d44, 8975268, 897526c, fed2d464, fed2d6d0, 8b5b
400) + 7e
fe7805f6 __1cMthread_entry6FpnKJavaThread_pnGThread__v_ (8b5b400, 8b5b400) + d2
fe77cbe4 __1cKJavaThreadRthread_main_inner6M_v_ (8b5b400) + 4c
fe77cb8e __1cKJavaThreadDrun6M_v_ (8b5b400) + 182
feadbd59 java_start (8b5b400) + f9
feed59a9 _thr_setup (745c5200) + 4e
feed5c90 _lwp_start (745c5200, 0, 0, 74233ff8, feed5c90, 745c5200)
系统信息:
# uname -a
SunOS xxxx 5.10 Generic_137138-09 i86pc i386 i86pc
# java -version
java version "1.6.0_11"
Java(TM) SE Runtime Environment (build 1.6.0_11-b03)
Java HotSpot(TM) Server VM (build 11.0-b16, mixed mode)
# ulimit -a
time(seconds) unlimited
file(blocks) unlimited
data(kbytes) unlimited
stack(kbytes) 10240
coredump(blocks) unlimited
nofiles(descriptors) 256
memory(kbytes) unlimited
使用的 jvm 参数:
java -Xms1024M -Xmx2048M -verbose:gc -Xloggc:logs/gc.log -server com.example.MyApplication
如果您发现缺少某些信息,请发表评论,我会尝试添加它们。
【问题讨论】:
-
JVM 可以写启动目录和/或当前工作目录吗?你认为崩溃的原因是内存泄漏,对象太多,看到任何核心文件是不寻常的这应该发生一个优雅的 OutOfMemoryError。除非有一些 JNI 错误。崩溃处理程序(写出 hs_err_pid*.log 的代码)可能会崩溃。也许在正在运行的进程上运行系统调用跟踪以观察它在其生命结束时所做的事情(即您应该能够查看崩溃处理程序是否崩溃,以及它是否尝试创建任何文件 hs_err_pid*.log)。在 Linux 上Solaris“桁架”上的“strace”
-
感谢您的回答。我确信工作目录是可写的(原因有两个:jvm 是以 root 权限运行的,并且它在前面已经成功编写过)。一般来说,应用程序本身不使用 jni 代码,也不是 jar 依赖项。但问题还是一样,为什么核心转储而没有 hs_rr_pid*.log 文件? Solaris内核是否有可能发送“核心转储”信号之一,即:developers.sun.com/solaris/articles/signalprimer.html?
-
如果你逐渐减少 -Xmx1700M 可以让进程抛出 OutOfMemoryError 吗?在 Solaris 上最大可用的 -Xmx 值是多少,例如,在 32 位 Windows 上大约是 1800M(因为默认情况下内核的上限为 2Gb,而 DLL/共享数据/堆栈占用大约 200M。您是否设法在获得有用输出的过程?您的“ulimit -a”设置是什么(例如来自 bash shell)。
-
那么你的意思是,低堆栈限制,过多的虚拟机使用可能会导致这种情况?
-
这并不是一个低堆栈限制,除非你正在做大量的回收并需要大量的堆栈空间。 “ulimit -Ha”可能表示硬限制是无限的,我希望 JVM 可以根据需要进行相应的管理。 JVM 堆栈和 C 语言堆栈是不同的。程序有多少个应用程序线程?我希望“truss”可以指示发生了什么信号,以及是否/何时用尽堆(内核拒绝通过 brk/sbrk 系统调用提供更多堆。在 Linux 下,所有这些都可以使用“strace”进行审计)。我建议通过减少 -Xmx 您可能可以获得受控的 OOM。
标签: java jvm solaris segmentation-fault jvm-crash