我们有一个JAVA应用程序,它通过消耗一些(未知的?)来破坏我们的红帽服务器(30个内核/512 cores )。重新获得阻止其他组件创建新线程的资源,我们目前正在解决这个问题,在每次问题出现时,我们都会杀死垃圾处理线程的进程--大约每15天--我们试图在/etc/security/limits.conf上设置巨大的值,但是在达到这个限制之前,我们已经解决了这个问题。
上一次使用ps -efL wc -l计算线程时,10000线程对我们的猛兽来说是很多,知道当时CPU/RAM消耗很低吗?我使用gstack来试图找出它被困在哪里,但是由于它是一个JAVA程序,所以它是否有意义?但是我可以在那里识别一个模式: 9000个线程中的大多数看起来如下:
Thread 9049 (Thread 0x7f43d5087700 (LWP 123925)):
#0 0x00007f43d791e705 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1 0x00007f43d6a94f33 in os::PlatformEvent::park() () from /opt/3pp/jdk1.8.0_25/jre/lib/amd64/server/libjvm.so
#2 0x00007f43d6a58e67 in Monitor::IWait(Thread*, long) () from /opt/3pp/jdk1.8.0_25/jre/lib/amd64/server/libjvm.so
#3 0x00007f43d6a59786 in Monitor::wait(bool, long, bool) () from /opt/3pp/jdk1.8.0_25/jre/lib/amd64/server/libjvm.so
#4 0x00007f43d6c48e1b in GangWorker::loop() () from /opt/3pp/jdk1.8.0_25/jre/lib/amd64/server/libjvm.so
#5 0x00007f43d6a9bd48 in java_start(Thread*) () from /opt/3pp/jdk1.8.0_25/jre/lib/amd64/server/libjvm.so
#6 0x00007f43d791adf5 in start_thread () from /lib64/libpthread.so.0
#7 0x00007f43d722f1ad in clone () from /lib64/libc.so.6
Thread 9048 (Thread 0x7f43d4f86700 (LWP 123926)):
#0 0x00007f43d791e705 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1 0x00007f43d6a94f33 in os::PlatformEvent::park() () from /opt/3pp/jdk1.8.0_25/jre/lib/amd64/server/libjvm.so
#2 0x00007f43d6a58e67 in Monitor::IWait(Thread*, long) () from /opt/3pp/jdk1.8.0_25/jre/lib/amd64/server/libjvm.so
#3 0x00007f43d6a59786 in Monitor::wait(bool, long, bool) () from /opt/3pp/jdk1.8.0_25/jre/lib/amd64/server/libjvm.so
#4 0x00007f43d6c48e1b in GangWorker::loop() () from /opt/3pp/jdk1.8.0_25/jre/lib/amd64/server/libjvm.so
#5 0x00007f43d6a9bd48 in java_start(Thread*) () from /opt/3pp/jdk1.8.0_25/jre/lib/amd64/server/libjvm.so
#6 0x00007f43d791adf5 in start_thread () from /lib64/libpthread.so.0
#7 0x00007f43d722f1ad in clone () from /lib64/libc.so.6另外,在我使用gcore -o /tmp/dump.txt终止进程之前,这是获取java进程核心文件的正确方法吗?
当我尝试使用gdb查看时,我得到没有调试符号和而不是核心转储,这是检查此类文件的正确方法吗?
M1:~# gdb /opt/3pp/jre/bin/java /tmp/dump.txt.123913
GNU gdb (GDB)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /opt/3pp/jre/bin/java...(no debugging symbols
"/tmp/dump.txt.123913" is not a core dump: File format not recognized
Missing separate debuginfos, use: debuginfo-install jre1.8.0_25-1.8.0_25-fcs.x86_64提前谢谢你的时间。
发布于 2019-10-29 22:58:15
我统计了上一次使用ps -efL \ wc -l的线程,10000线程对我们的猛兽来说是很多,知道当时CPU/RAM消耗很低吗?
这不是一个微不足道的线程数量,但不,10K线程不是的太多,特别是对30核心机器。我目前使用的4台核心Windows桌面有~3K。
我使用g堆栈试图找出它被困在哪里,但是由于它是一个JAVA程序,所以如果输出有意义,那么idk?
我从未尝试过使用本机线程堆栈来调试Java,但在我看来,这个堆栈跟踪看起来像是一个“停放”的线程。换句话说,某个线程池中的线程没有什么可做的,所以它在等待工作。有关更多细节,请参见这答案。
另外,在终止使用gcore -o /tmp/dump.txt的进程之前,这是获取java进程核心文件的正确方法吗?
它可能有一些价值,但我建议使用特定于java的工具来完成这项工作。首先想到的是JDK附带的jcmd。这里有一个链接让你开始吧。Java9的版本有一些更好的文件,而且非常类似。
我特别要做的是使用jcmd的jcmd命令打印java级别的堆栈跟踪,并使用GC.heap_dump将整个java堆转储到.hprof文件中,稍后可以通过垫子等工具进行分析。
如果在“商业特色”中使用JDK 8,还可以启用跟踪流程执行情况的Java飞行记录器。JFR创建的文件可以使用甲骨文的“任务控制”打开,也可以使用另一种“任务控制”(如从阿祖尔来的,叫做祖鲁 )打开。
最后,您还可以尝试使用J控制台连接到进程,这是JDK附带的另一个工具。
祝好运。
发布于 2019-10-30 06:42:01
我将给您一个关于JVM核心文件的一般建议,这样您就可以选择是否深入研究它。
使用gcore生成的java核心文件有用吗?
它确实很有用,但是如果您不知道具体的JVM实现,它看起来会很混乱。堆栈跟踪是完全正确的,并且崩溃肯定不会因为调用pthread_cond_wait而发生(除非线程本身是错误的,这是非常不可能的)。
我们有一个JAVA应用程序正在崩溃
你做过记忆测试吗?在绝大多数情况下,JVM HotSpot实现是高度可靠的。
这是获取java进程核心文件的正确方法吗?
您也可以在gdb中使用generate-core-file。
没有调试符号
您已经显示了带有调试符号的堆栈跟踪。可能是核心文件出了问题。试试gdb generate-core-file
如果您想深入研究HotSpot核心转储,那么我可以建议执行以下一系列操作:
info threadsthread N转到这个线程,其中N是“崩溃线程”号。disas来封装函数并找出导致崩溃的指令如果您由于不正确使用Bus Error之类的东西而崩溃,事情会变得复杂起来。如果您在JIT编译的方法中崩溃,事情会变得更加复杂,这样bt、disas和朋友就没用了。可能的方法是从N法中转储由偏移编译的代码,并试图找出哪里出了问题。
https://stackoverflow.com/questions/58615796
复制相似问题