概述为什么这个Java进程无法终止?
我在构build服务器上有一个间歇性的问题,构build中的Java进程无法终止,似乎永远继续运行(使用100%的cpu)永远(我已经看到它在周末运行2天以上通常需要大约10分钟)。 kill -9 pID似乎是停止进程的唯一方法。
我已经尝试过在进程中调用kill -QUIT pID ,但似乎没有产生任何堆栈跟踪到STDOUT(也许它没有响应信号?)。 没有-F强制选项的Jstack似乎无法连接到正在运行的JVM,但是使用强制选项,它会产生下面的输出。
不幸的是,即使有这个堆栈跟踪,我也看不到有任何明显的path可供进一步调查。
据我可以告诉它显示了两个已经运行Object.wait的“BLOCKED”线程(它们的堆栈似乎只包含核心Java代码,没有我们的代码),第三个是没有堆栈输出的“IN_VM”。
使用linux错误注入框架
为什么我们需要在windows平台上有pdb文件的时候使用map文件呢?
解释gfortran错误追溯
在托pipe服务中检测到CRTdeBUGging堆损坏
任何方式来停止x86_64上的c + +标准库的未alignment的访问?
我应该采取哪些步骤来收集有关问题原因的更多信息(或者更好,但我该如何解决)?
$ /opt/jdk1.6.0_29/bin/Jstack -l -F 5546
附加到进程ID 5546,请稍候…
deBUGging器成功连接。
检测到服务器编译
JVM版本是20.4-b02
死锁检测:
没有发现死锁。
使用Printezis位查找对象大小并跳过…
线程5555 :(状态= BLOCKED)
locking拥有同步器:
– 没有
线程5554 :(状态= BLOCKED)
– java.lang.Object.wait(long)@ bci = 0(解释帧)
– java.lang.ref.ReferenceQueue.remove(long)@ bci = 44,line = 118(Interpreted frame)
– java.lang.ref.ReferenceQueue.remove()@ bci = 2,line = 134(Interpreted frame)
– java.lang.ref.Finalizer $ FinalizerThread.run()@ bci = 3,line = 159(Interpreted frame)
locking拥有同步器:
– 没有
线程5553 :(状态= BLOCKED)
– java.lang.Object.wait(long)@ bci = 0(解释帧)
– java.lang.Object.wait()@ bci = 2,line = 485(Interpreted frame)
– java.lang.ref.Reference $ ReferenceHandler.run()@ bci = 46,line = 116(Interpreted frame)
locking拥有同步器:
– 没有
线程5548 :(状态= IN_VM)
locking拥有同步器:
– 没有
(Java版本1.6.0更新29,在ScIEntific linux版本6.0上运行)
更新:
运行strace -f -p 894产生了一个似乎层出不穷的…
[pID 900] sched_yIEld() = 0 [pID 900] sched_yIEld() = 0 …
然后当Ctrl-Cd
Process 894 detached … Process 900 detached … Process 909 detached
jmap -histo 894不连接,但jmap -F -histo 894返回…
附加到进程ID 894,请稍候…
deBUGging器成功连接。
检测到服务器编译
JVM版本是20.4-b02
遍历堆。 可能还要等一下…
使用Printezis位查找对象大小并跳过…
使用Printezis位查找对象大小并跳过…
对象直方图:
数字#实例#字节类描述
————————————————– ————————
1:11356 1551744 * Methodklass
2:11356 1435944 * ConstMethodklass
3:914 973488 * ConstantPoolKlass
4:6717 849032 char []
5:16987 820072 * SymbolKlass
6:2305 686048 byte []
7:914 672792 * InstanceKlassKlass
8:857 650312 * ConstantPoolCacheKlass
9:5243 167776 java.lang.String
10:1046 108784 java.lang.class
11:1400 87576短[]
12:1556 84040 * System ObjArray
13:1037 64584 int []
14:103 60152 * ObjArrayKlassKlass
15:622 54736 java.lang.reflect.Method
16:1102 49760 java.lang.Object []
17:937 37480 java.util.TreeMap $ Entry
18:332 27960 java.util.HashMap $ Entry []
19:579 27792 java.nio.HeapByteBuffer
20:578 27744 java.nio.HeapCharBuffer
21:1021 24504 java.lang.StringBuilder
22:1158 24176 java.lang.class []
23:721 23072 java.util.HashMap $ Entry
24:434 20832 java.util.TreeMap
25:689 18936 java.lang.String []
26:238 17440 java.lang.reflect.Method []
27:29 16800 * MethodDataKlass
28:204 14688 java.lang.reflect.FIEld
29:330 13200 java.util.linkedHashMap $ Entry
30:264 12672 java.util.HashMap
…
585:1 16 java.util.linkedHashSet
586:1 16 sun.rmi.runtime.NewThreadAction $ 2
587:1 16 java.util.Hashtable $ EmptyIterator
588:1 16 java.util.Collections $ EmptySet
总计:79700 8894800
堆遍历花费了1.288秒。
GDB – “线程适用所有BT满”给空白
如何将更新同步到windows符号存储?
windbg首先连接,然后在内核deBUGging过程中卡住“DeBUGgee not connected。”消息
Visual Studio 2013专业版无法启动
Visual Studio c#远程deBUGgingclosureswindows服务
你总是可以用strace -f -p pID来查看Java进程正在做什么。 从它的外观(你不能得到没有-F的Jstack ,并且线程5548显示没有调用堆栈并且是IN_VM),看起来线程5548正在花费太多时间来做某事,或者可能处于某种无限循环。
这可能是由于内存不足造成的。 我会尝试两件事情:
通过添加JVM参数在OutOfMemory上启用自动堆转储
-XX:+ HeapDumpOnOutOfMemoryError XX:HeapDumpPath = / tmp
尝试使用JConsole连接到您的JVM,并查看是否有任何不寻常的模式
我会怀疑一个内存问题。 您可能想要使用jstat来观察进程,并在需要杀死进程的时间周围使用jmap进行堆转储。 看看jstat是否表示连续的GC。 另外,您可能需要检查一般系统的运行状况(打开文件描述符,网络等)。 内存将是最简单的,所以我强烈建议从它开始。
当进程正常运行时,通过Jstack -F(-F必须存在,它产生不同于Jstack的快照)。 线程号不是Thread.ID,而是系统号。 5548似乎是在Finalizer和RefCounter之前创建的(它们不是问题的根源),所以它应该是一个GC线程或者一个编译器。
100%可能意味着监视器中的一些错误。 Java(热点)显示器使用非常简单的自旋锁定机制来确保所有权。
当然,附上一个调试器 – GDB来检查进程到底在哪里。
线程5554可能表明你有很多的finalize方法的对象,和/或finalize方法的一些问题。 看这个可能是值得的。
我对Jstack并不熟悉,但看起来它输出的信息更少,我更熟悉的线程转储。 尝试获取线程转储可能有用: kill -QUIT java_pID 。 请注意,转储到标准输出可能是控制台或记录文件,具体取决于您的设置。
如果很难确定stdout被引导到哪里,并且假定它正在转到一个文件,那么可以使用最近修改时间来查找候选文件。 这是建议在这篇博客的评论:
你可以在根目录下运行find [2]命令,找出最近x秒内发生了什么变化。 我通常使用find来帮助我访问在过去10分钟内更改的所有日志,例如:find / var / tomcat -mmin -3 -print(打印出在/ var / tomcat下修改的所有文件分钟)。
请注意,如果您正在使用-Xrs运行JVM,这意味着SIGQUIT信号处理程序将不会被安装,您将无法使用这种方式请求线程转储。
我遇到了类似的问题,我的JBOSS jvm得到了一个无限循环,最终它得到了OutOfMemory,我不能杀死这个进程而是kill -9。 我怀疑在大多数情况下的内存问题。
以下是一些工具,您可以使用这些工具本地化消耗cpu的进程部分:
perf / oprofile ,特别是opannotate – 非常适合查看地狱代码消耗的周期
strace , gstack / gdb (正如别人所说)
systemtap功能非常强大,但是与基于ptrace的工具一样,如果你的问题不涉及系统调用,那么效率就会低很多。
总结
以上是内存溢出为你收集整理的为什么这个Java进程无法终止?全部内容,希望文章能够帮你解决为什么这个Java进程无法终止?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
请登录后查看评论内容