[讨论] JVM Crash 请教原因

aronlulu 2012-03-16
也都是坏的:
hsdb> mem 0x7f0881bf0
0x00000007f0881bf0: 0x00000007f0783ef0 

hsdb> inspect 0x00000007f0881bf0
Error: sun.jvm.hotspot.oops.UnknownOopException
hsdb> mem 0x5755d33b8
0x00000005755d33b8: 0xaebebb2baebebb2b 

hsdb> inspect 0x00000005755d33b8
Error: sun.jvm.hotspot.oops.UnknownOopException
hsdb> mem 0x5755dc120
0x00000005755dc120: 0xaebc3356aebebb4f 

hsdb> inp^[[D^[[3~
Unrecognized command.  Try help...
hsdb> inspect 0x00000005755dc120
Error: sun.jvm.hotspot.oops.UnknownOopException
hsdb> 
RednaxelaFX 2012-03-16
嗯这就糟糕了…啊,不过在adjust_pointer阶段前面的klass、referent等指针都已经修正过了,而它们原本指向的对象还没移动,这里要看到真正的对象内容得另外想办法。

对了,能不能帮忙看看这个信息:
jstack <你的java命令的全路径> <你的core dump文件的路径>

看看有没有什么Java线程在做System.gc()?如果有的话,能否加上-XX:+ExplicitGCInvokesConcurrent 来跑你的应用,看看是否还会crash?

再确认一下,这种crash在你的环境里是不是能经常、稳定的重现?
如果是,现在我会做的是两种建议:
1、像前面说的那样,找一个会出问题的环境打开heap verification。这样的代价是full GC时会稍微慢些,但能发现堆里存在不一致性的地方,发现之后再做分析;
2、试试把会出问题的环境里的JDK换成JDK6u32的预览版:http://jdk6.java.net/download.html。这个版本有修正过一些CMS GC与弱引用处理相关的bug。或许能有帮助。
如果仍然crash的话建议提交一个bug report到Oracle去,然后在邮件列表上讨论一下:hotspot-gc-use
aronlulu 2012-03-16
今天上午又crash了一次,按照你说的,我搜了一下jstack出来的信息,没有gc,我是直接搜gc关键字的,没搜到,基本上全是损坏数据的异常信息。不知道这样做对不对,请指教。
我已经把那几个参数加上了,下次重现的时候看能不能看到些什么。
如果确实是CMS回收问题的话,那应该换,关键是现在拿不出证据来说明这个是JVM的bug。
RednaxelaFX 2012-03-16
aronlulu 写道
今天上午又crash了一次,按照你说的,我搜了一下jstack出来的信息,没有gc,我是直接搜gc关键字的,没搜到,基本上全是损坏数据的异常信息。不知道这样做对不对,请指教。
我已经把那几个参数加上了,下次重现的时候看能不能看到些什么。
如果确实是CMS回收问题的话,那应该换,关键是现在拿不出证据来说明这个是JVM的bug。

jstack检查core dump的输出是怎样的信息?怎么个损坏法?
jstack的这种工作模式报错不一定是因为你的JVM出错了,有可能是jstack自身的bug。有些bug一直还没修好。

只要你没在代码里用sun.misc.Unsafe,依赖的所有的库都没有用这个,然后也没通过JNI用什么奇怪的native库,那能出问题的就只有JVM了——即便根源不是它,它至少应该处理得更和谐一些。所以也算是bug。

你的应用有没有挂载什么外部的profiler或者什么agent之类的?
另外,使用了一些什么native库?
能进入crash里看到的执行路径的只有几种可能,
1、System.gc()
2、外部的agent通过JVMTI调用了GC
3、jmap -histo:live、jmap -dump:live之类的外部工具要求做GC
4、通过JNI调用了某些native函数,里面使用了Critical系的API
如果你确认没有第一中,那么后面的几种情况也请关注一下。

我关注这个问题因为6u29上能发生的问题也有可能会影响到我们这边。如果再折腾一下还是没头绪的话,恐怕你还是得发邮件去hotspot-gc-use邮件列表问问了。
aronlulu 2012-03-16
果然像你所说的那样,是jstack自身的原因:
Thread 6000: (state = BLOCKED)
Error occurred during stack walking:

Thread 5999: (state = BLOCKED)
Error occurred during stack walking:

让我感到奇怪的是,我们的应用已经跑了大半年了,经过十几台服务器的洗礼。就这台挂了,不知道是不是因为这台服务器上有什么特殊程序会触发GC失败。
至于调用system.gc,这个我btrace还没挂上去,我发现btrace监听system.gc必须把脚本嵌入启动项,外围脚本我试过好像监听不到。
我们有拉起服务的监听,但是不只有这台主机,其他主机也有,所以这个应该不是原因。
外部工具可以排除。
jni我们程序中肯定没有,引用的jar就不确定了。
邮件列表讨论,由于公司各方面因素限制,应该搞不起来。
我还想请教的问题是:
我如果把回收方式改成并行方式,对于这种内存完全够用,CPU也完全够用的服务器来说,会有多大区别。
我当初采用CMS是为了让应用暂停时间最少,但是我不确定对于高性能服务器来说,这个暂停时间并行跟并发到底有多大区别,不知道有没有类似经验可以分享。
还有jdk7 有了G1后,是不是CMS就变得很鸡肋了。
RednaxelaFX 2012-03-16
我之前试attach方式监视System.gc()能行。但是我的开发环境那台机器有点问题,换到我的Windows的笔记本上执行过OK。

jstack有问题的话试试用pstack来捞出core dump里的native stack trace。希望能多看到些信息。

你的应用的GC堆挺大的,换成UseParallelOldGC应该会增长暂停时间。但大概会到什么量级我也没把握。

现在HotSpot VM已经没有在给CMS开发新改进了。但G1感觉仍然不够成熟。暂时还是得靠CMS来达到low pause的目的。

公司的保密限制什么的,如果你购买Oracle的Java for Business,合同上可以带有NDA,就不怕泄密。但那必然是要钱的,呵呵。
Global site tag (gtag.js) - Google Analytics