簡體   English   中英

使用 gcore 生成的 java 核心文件有用嗎?

[英]Is a java corefile generated using gcore useful?

我們有一個JAVA應用程序通過消耗一些(未知?)資源來阻止其他組件創建新線程,從而使我們的redhat服務器(30 核 / 512Go ram)崩潰,我們目前正在通過終止向線程發送垃圾郵件的進程來解決這個問題每次出現問題時,大約每 15 天出現一次,我們嘗試在/etc/security/limits.conf上設置巨大的值,但在達到該限制之前我們就遇到了問題。

我上次使用ps -efL |計算了線程數。 wc -l ,對於我們的野獸來說,知道當時 CPU/RAM 消耗很低, 10000個線程是不是很多? 我使用gstack試圖找出它卡在哪里,但是因為它是一個 JAVA 程序 idk 如果 output 有意義嗎? 但我可以在那里識別出一個模式: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

在此先感謝您的時間。

我上次使用 ps -efL | 計算了線程數。 wc -l,知道當時 CPU/RAM 消耗很低,對於我們的野獸來說,10000 個線程是不是很多?

這不是一個微不足道的線程數,但不,10K 線程並不是那么多,尤其是對於 30 核機器。 我目前使用的 4 核 Windows 桌面大約有 3K。

我使用 gstack 試圖找出它卡在哪里,但是因為它是一個 JAVA 程序 idk 如果 output 有意義嗎?

我從未嘗試過使用本機線程堆棧調試 Java,但對我來說,堆棧跟蹤看起來像一個“停放”的線程。 換句話說,某個線程池中的一個線程沒有任何事情可做,所以它正在等待工作。 有關更多詳細信息,請參閱答案。

同樣在殺死我使用 gcore -o /tmp/dump.txt 的進程之前,它是獲取 java 進程的核心文件的正確方法嗎?

它可能有一些價值,但我建議使用特定於 java 的工具來完成這項工作。 首先想到的是 JDK 附帶的jcmd 這是一個幫助您入門的鏈接 Java 9 的版本有一些更好的文檔,並且非常相似。

我具體要做的是使用jcmdThread.print命令打印 java 級堆棧跟蹤,並GC.heap_dump將整個 java 堆轉儲到.hprof文件中,以后可以通過MAT等工具進行分析。

如果您使用的是具有“商業功能”的 JDK 8,您還可以啟用JFR(跟蹤流程執行的 Java Flight Recorder。JFR創建的文件可以使用Oracle 的“任務控制”或替代“任務控制”,例如來自 Azul 的稱為 Zulu的。

最后,您還可以嘗試使用jconsole連接到進程,這是 JDK 附帶的另一個工具。

祝你好運。

我會給你一個關於 JVM 核心文件的一般建議,這樣你就可以選擇是否深入研究它。

使用 gcore 生成的 java 核心文件有用嗎?

它確實很有用,但如果您不知道特定的 JVM 實現,它看起來就像一團糟。 堆棧跟蹤完全沒有問題,並且由於調用pthread_cond_wait肯定不會發生崩潰(除非 pthread 本身是錯誤的,這是極不可能的)。

我們有一個崩潰的 JAVA 應用程序

您是否運行了 memory 測試? JVM HotSpot 實現在絕大多數情況下都非常可靠。

獲取 java 進程的核心文件是正確的方法嗎?

您還可以在 gdb 中使用generate-core-file

沒有調試符號

您已經使用調試符號顯示了堆棧跟蹤。 核心文件可能有問題。 嘗試gdb generate-core-file

如果您想深入研究 HotSpot 核心轉儲,那么我可以建議執行以下操作序列:

  1. 查找“崩潰線程”的info threads
  2. Go 到這個線程, thread N ,其中N是“崩潰線程”編號
  3. disas拆卸 function 並找出導致崩潰的指令
  4. 如果由於取消引用垃圾指針而發生這種情況,請將其反轉以找出值的來源

如果由於mmap使用不正確等原因導致Bus Error崩潰,事情就會變得復雜。 如果您在 JIT 編譯方法中崩潰,事情會變得更加復雜,因此btdisas和朋友將無用。 go 的可能方法是通過code_offsetnmethod轉儲編譯代碼並嘗試找出問題所在。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM