วิธีรับเธรดและฮีปของกระบวนการ Java บน Windows ที่ไม่ได้ทำงานในคอนโซล


232

ฉันมีแอปพลิเคชัน Java ที่ฉันเรียกใช้จากคอนโซลซึ่งจะดำเนินการกับกระบวนการ Java อื่น ฉันต้องการรับเธรด / กองฮีปของกระบวนการย่อยนั้น

ใน Unix ฉันสามารถทำได้kill -3 <pid>แต่ใน Windows AFAIK วิธีเดียวที่จะได้รับการถ่ายโอนข้อมูลเธรดคือ Ctrl-Break ในคอนโซล แต่นั่นทำให้ฉันถ่ายโอนข้อมูลของกระบวนการหลักไม่ใช่ลูก

มีวิธีอื่นในการรับการถ่ายโอนข้อมูลฮีปนั้นหรือไม่


คำตอบ:


376

คุณสามารถใช้jmapจะได้รับการถ่ายโอนข้อมูลของกระบวนการใด ๆ pidที่ทำงานสมมติว่าคุณรู้ว่า

ใช้ Task Manager pidหรือตรวจสอบทรัพยากรที่จะได้รับ แล้วก็

jmap -dump:format=b,file=cheap.hprof <pid>

เพื่อรับฮีปสำหรับกระบวนการนั้น


jmap ไม่พร้อมใช้งานสำหรับ JDK5 ใน windows มีวิธีการถ่ายโอนข้อมูลกับ JDK5 บน windows หรือไม่?
Santron Manibharathi

173
หัวข้อนี้ได้กลายเป็นที่นิยมจนฉันเพิ่งได้ยินใครบางคนอ้างถึงกองการถ่ายโอนข้อมูลเป็น "cheap.bin"
mjaggard

7
ชื่อไฟล์ที่ตรงไปตรงมามากขึ้น: "heap.hprof" เนื่องจากอยู่ในรูปแบบ HPROF
MGM

1
ตรวจสอบให้แน่ใจว่าใช้ผู้ใช้ที่ถูกต้องซึ่งเริ่มกระบวนการจาวา ในกรณีของฉันมันเป็น tomcat8 ps -C java -o pid sudo -u tomcat8 jmap -dump: format = b, file = <filename> <pid>
bitsabhi

115

คุณกำลังสับสน java dumps ที่ต่างกันสองตัว kill -3สร้างการถ่ายโอนข้อมูลเธรดไม่ใช่กองการถ่ายโอนข้อมูล

เธรดดัมพ์ = การติดตามสแต็กสำหรับแต่ละเธรดในเอาต์พุต JVM ไปยัง stdout เป็นข้อความ

Heap dump = เนื้อหาหน่วยความจำสำหรับเอาต์พุตกระบวนการ JVM ไปยังไฟล์ไบนารี

หากต้องการใช้เธรดดัมพ์บน Windows CTRL+ BREAKหาก JVM ของคุณเป็นกระบวนการทำงานเบื้องหน้าเป็นวิธีที่ง่ายที่สุด หากคุณมีเชลล์ที่เหมือนยูนิกซ์บน Windows เช่น Cygwin หรือ MobaXterm คุณสามารถใช้kill -3 {pid}เหมือนที่คุณสามารถทำได้ใน Unix

หากต้องการถ่ายโอนเธรดใน Unix CTRL+ Cหาก JVM ของคุณเป็นกระบวนการkill -3 {pid}ทำงานเบื้องหน้าหรือจะทำงานตราบใดที่คุณได้รับ PID ที่ถูกต้องสำหรับ JVM

ด้วยทั้งสองแพลตฟอร์ม Java มาพร้อมกับยูทิลิตี้ต่าง ๆ ที่สามารถช่วยได้ สำหรับการทิ้งเธรดjstack {pid}เป็นทางออกที่ดีที่สุดของคุณ http://docs.oracle.com/javase/1.5.0/docs/tooldocs/share/jstack.html

เพียงเพื่อเสร็จสิ้นคำถามการถ่ายโอนข้อมูลออก: การทิ้งกองมักไม่ได้ใช้เพราะยากต่อการตีความ แต่พวกเขามีข้อมูลที่เป็นประโยชน์มากมายในพวกเขาหากคุณทราบว่า / วิธีดูพวกเขา การใช้งานบ่อยที่สุดคือการค้นหาการรั่วไหลของหน่วยความจำ เป็นวิธีปฏิบัติที่ดีในการตั้งค่า-Dบนบรรทัดคำสั่ง java เพื่อให้การถ่ายโอนข้อมูลฮีปถูกสร้างขึ้นโดยอัตโนมัติเมื่อ OutOfMemoryError -XX:+HeapDumpOnOutOfMemoryError แต่คุณสามารถเปิดใช้งานการถ่ายโอนข้อมูลด้วยตนเองได้เช่นกัน jmapวิธีที่ใช้กันมากที่สุดคือการใช้ยูทิลิตี้จาวา

หมายเหตุ:ยูทิลิตี้นี้ไม่สามารถใช้ได้กับทุกแพลตฟอร์ม ตั้งแต่ JDK 1.6 jmapมีให้บริการบน Windows

ตัวอย่างบรรทัดคำสั่งจะมีลักษณะเป็นอย่างไร

jmap -dump:file=myheap.bin {pid of the JVM}

ผลลัพธ์ "myheap.bin" นั้นไม่สามารถอ่านได้โดยมนุษย์ (สำหรับพวกเราส่วนใหญ่) และคุณจะต้องใช้เครื่องมือในการวิเคราะห์ การตั้งค่าของฉันคือ MAT http://www.eclipse.org/mat/


3
บน linux Ctrl-C ของฉันขัดจังหวะ (ยุติ) ฉันทำ Ctrl- \
nafg

พิจารณาสิ่งนี้และผลกระทบทั่วไปของ "การใช้เธรดดัมพ์บน Windows, CTRL + BREAK" มันขึ้นอยู่กับการตัดสินใจทางวิศวกรรมของผู้ผลิต FE, Lenova, IIRC คือ cntrl + fn + p
ChiefTwoPencils

30

ฉันคิดว่าวิธีที่ดีที่สุดในการสร้างไฟล์. hprof ในกระบวนการ Linux คือการใช้คำสั่งjmap ตัวอย่างเช่น:jmap -dump:format=b,file=filename.hprof {PID}


19

นอกจากการใช้ jconsole / visualvm ที่กล่าวถึงแล้วคุณสามารถใช้ jstack -l <vm-id>ในหน้าต่างบรรทัดคำสั่งอื่นและจับเอาท์พุทนั้น

<vm-id> สามารถพบได้โดยใช้ตัวจัดการงาน (เป็นรหัสกระบวนการใน windows และ unix) หรือการใช้ jpsหรือใช้

ทั้งสองjstackและjpsรวมอยู่ใน Sun JDK เวอร์ชัน 6 และสูงกว่า


เครื่องมือเหล่านี้ไม่รองรับใน Java 1.6 Java 1.6 มี jconsole เท่านั้น
Vanchinathan Chandrasekaran

7
คุณอาจจะสับสน JDK และ JRE ฉันพูดถึง JDK อย่างชัดเจน ดูเอกสารประกอบสำหรับเครื่องมือ: download.oracle.com/javase/6/docs/technotes/tools/share/
......

17

ฉันแนะนำ Java VisualVM ที่แจกจ่ายกับ JDK (jvisualvm.exe) มันสามารถเชื่อมต่อแบบไดนามิกและเข้าถึงหัวข้อและกอง ฉันพบว่ามีค่าสำหรับปัญหาบางอย่าง


2
นั่นเป็นส่วนใหญ่ที่ไม่สามารถทำได้เนื่องจากมีโอเวอร์เฮดติดอยู่และโดยทั่วไปจะมีการดึงเธรดออกจากเครื่องผลิต
Hammad Dar

คำถามเดิมเป็นเรื่องเกี่ยวกับกระบวนการ 'ไม่ทำงาน' เป็นไปได้ว่า jvisualvm ไม่สามารถเชื่อมต่อได้
Jaberino

3
@Jaberino: ไม่มันเกี่ยวกับกระบวนการ Java ที่กำลังทำงานอยู่ใน Windows โดยไม่มีคอนโซลที่เกี่ยวข้อง
Lawrence Dol

ในรุ่นล่าสุด Java Java VisualVM ถูกแทนที่ด้วยเครื่องJMC / JFR ดูเพิ่มเติมJVisualVM และ Java Mission Control แตกต่างกันอย่างไร
Vadzim

16

หากคุณใช้เซิร์ฟเวอร์ -jre 8 ขึ้นไปคุณสามารถใช้สิ่งนี้:

jcmd PID GC.heap_dump /tmp/dump

1
ในระบบการผลิตส่วนใหญ่เรามี jre และไม่ใช่ jdk เท่านั้น ดังนั้นนี่ช่วย
Pragalathan M

15

ลองตัวเลือกใดตัวเลือกหนึ่งด้านล่าง

  1. สำหรับ JVM 32 บิต:

    jmap -dump:format=b,file=<heap_dump_filename> <pid>
  2. สำหรับ JVM 64 บิต (อ้างอย่างชัดเจน):

    jmap -J-d64 -dump:format=b,file=<heap_dump_filename> <pid>
  3. สำหรับ 64 บิต JVM พร้อมอัลกอริธึม G1GC ในพารามิเตอร์ VM (เฉพาะ live object heap เท่านั้นที่ถูกสร้างด้วยอัลกอริทึม G1GC):

    jmap -J-d64 -dump:live,format=b,file=<heap_dump_filename> <pid>

คำถาม SE ที่เกี่ยวข้อง: ข้อผิดพลาดการถ่ายโอนข้อมูล Java heap กับคำสั่ง jmap: EOF ก่อนกำหนด

ลองดูที่ตัวเลือกต่าง ๆ ของjmapที่บทความนี้


13

หากคุณต้องการ heapdump จากหน่วยความจำไม่เพียงพอคุณสามารถเริ่ม Java ด้วยตัวเลือก -XX:-HeapDumpOnOutOfMemoryError

หน้าการอ้างอิง cf JVM Options


ขอบคุณแดเนียล ไฟล์นี้ถูกสร้างขึ้นบนเครื่องที่ใช้ Windows มีเส้นทางเริ่มต้นหรือไม่
ลาวา

1
@lava คุณสามารถตั้งค่าพา ธ ผ่าน -XX: HeapDumpPath ดังที่อธิบายไว้ในหน้าตัวเลือก VM ของ Oracle
kamczak

น่ากลัว ฉันต้องการเรียกใช้การทดสอบในชั่วข้ามคืนโดยหวังว่าจะมีการรั่วไหลของหน่วยความจำ แต่เป็นห่วง OOM และความล้มเหลวในขณะที่ฉันไม่อยู่ มันสมบูรณ์แบบ
บาซิล

7

คุณสามารถเรียกใช้jconsole(รวมอยู่ใน SDK ของ Java 6) จากนั้นเชื่อมต่อกับแอปพลิเคชัน Java ของคุณ มันจะแสดงให้คุณเห็นทุกการทำงานของเธรดและการติดตามสแต็กของมัน


คำตอบที่ดีที่สุดโดยไกล! ยังไม่รู้เรื่องนี้จนถึงตอนนี้และมันใช้งานได้จริง!
Xerus

7

คุณสามารถส่งkill -3 <pid>จาก Cygwin คุณต้องใช้psตัวเลือกCygwin เพื่อค้นหากระบวนการ windows จากนั้นเพียงส่งสัญญาณไปยังกระบวนการนั้น


5

คุณต้องเปลี่ยนเส้นทางเอาต์พุตจากจาวาที่สองที่สามารถเรียกใช้งานไปยังไฟล์บางไฟล์ได้ จากนั้นใช้SendSignalเพื่อส่ง "-3"ไปยังกระบวนการที่สองของคุณ


แต่ jstack ต้องการที่จะเป็นทางเลือกที่เชื่อถือได้มากขึ้นบน Windows: stackoverflow.com/a/47723393/603516
Vadzim

3

หากคุณใช้ JDK 1.6 หรือสูงกว่าคุณสามารถใช้ jmapคำสั่งเพื่อถ่ายโอนกองฮีพของกระบวนการ Java ได้เงื่อนไขคือคุณควรรู้จัก ProcessID

หากคุณใช้ Windows Machine คุณสามารถใช้ตัวจัดการงานเพื่อรับ PID สำหรับเครื่อง Linux คุณสามารถใช้สายพันธุ์ของคำสั่งที่ชอบps -A | grep javaหรือ netstat -tupln | grep javaหรือtop | grep javaขึ้นอยู่กับการใช้งานของคุณ

จากนั้นคุณสามารถใช้คำสั่งเหมือนjmap -dump:format=b,file=sample_heap_dump.hprof 1234ที่ 1234 เป็น PID

มีเครื่องมือหลากหลายให้ตีความไฟล์ hprof ฉันจะแนะนำเครื่องมือ visualvm ของ Oracle ซึ่งใช้งานง่าย


3

หากคุณไม่สามารถ (หรือไม่ต้องการ) ใช้คอนโซล / เทอร์มินัลด้วยเหตุผลบางอย่างมีวิธีแก้ปัญหาอื่น คุณสามารถทำให้แอปพลิเคชัน Java พิมพ์เธรดดัมพ์สำหรับคุณ รหัสที่รวบรวมการติดตามสแต็กนั้นง่ายพอสมควรและสามารถแนบกับปุ่มหรือเว็บอินเตอร์เฟส

private static String getThreadDump() {
    Map<Thread, StackTraceElement[]> allStackTraces = Thread.getAllStackTraces();

    StringBuilder out = new StringBuilder();
    for (Map.Entry<Thread, StackTraceElement[]> entry : allStackTraces.entrySet()) {
        Thread thread = entry.getKey();
        StackTraceElement[] elements = entry.getValue();
        out.append(String.format("%s | prio=%d | %s", thread.getName(), thread.getPriority(), thread.getState()));
        out.append('\n');

        for (StackTraceElement element : elements) {
            out.append(element.toString()).append('\n');
        }
        out.append('\n');
    }
    return out.toString();
}

วิธีนี้จะส่งคืนสตริงที่มีลักษณะดังนี้:

main | prio=5 | RUNNABLE
java.lang.Thread.dumpThreads(Native Method)
java.lang.Thread.getAllStackTraces(Thread.java:1607)
Main.getThreadDump(Main.java:8)
Main.main(Main.java:36)

Monitor Ctrl-Break | prio=5 | RUNNABLE
java.net.PlainSocketImpl.initProto(Native Method)
java.net.PlainSocketImpl.<clinit>(PlainSocketImpl.java:45)
java.net.Socket.setImpl(Socket.java:503)
java.net.Socket.<init>(Socket.java:424)
java.net.Socket.<init>(Socket.java:211)
com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:59)

Finalizer | prio=8 | WAITING
java.lang.Object.wait(Native Method)
java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)

Reference Handler | prio=10 | WAITING
java.lang.Object.wait(Native Method)
java.lang.Object.wait(Object.java:502)
java.lang.ref.Reference.tryHandlePending(Reference.java:191)
java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

สำหรับผู้ที่สนใจรุ่น Java 8 ที่มีสตรีมรหัสจะมีขนาดกะทัดรัดยิ่งขึ้น:

private static String getThreadDump() {
    Map<Thread, StackTraceElement[]> allStackTraces = Thread.getAllStackTraces();
    StringBuilder out = new StringBuilder();
    allStackTraces.forEach((thread, elements) -> {
        out.append(String.format("%s | prio=%d | %s", thread.getName(), thread.getPriority(), thread.getState()));
        out.append('\n');

        Arrays.stream(elements).forEach(element -> out.append(element.toString()).append('\n'));
        out.append('\n');
    });
    return out.toString();
}

คุณสามารถทดสอบรหัสนี้ได้อย่างง่ายดายด้วย:

System.out.print(getThreadDump());

3

สคริปต์ต่อไปนี้ใช้ PsExec เพื่อเชื่อมต่อกับเซสชัน Windows อื่นเพื่อให้ทำงานได้แม้เมื่อเชื่อมต่อผ่านบริการเดสก์ท็อประยะไกล

ฉันเขียนสคริปต์ชุดเล็กสำหรับ Java 8 (ใช้PsExecและjcmd) ชื่อjvmdump.batซึ่งทิ้งกระทู้, heap, คุณสมบัติของระบบและ JVM args

:: set the paths for your environment
set PsExec=C:\Apps\SysInternals\PsExec.exe
set JAVA_HOME=C:\Apps\Java\jdk1.8.0_121
set DUMP_DIR=C:\temp

@echo off

set PID=%1

if "%PID%"=="" (
    echo usage: jvmdump.bat {pid}
    exit /b
)

for /f "tokens=2,3,4 delims=/ " %%f in ('date /t') do set timestamp_d=%%h%%g%%f
for /f "tokens=1,2 delims=: " %%f in ('time /t') do set timestamp_t=%%f%%g
set timestamp=%timestamp_d%%timestamp_t%
echo datetime is: %timestamp%

echo ### Version >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% VM.version >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"

echo. >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
echo ### Uptime >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% VM.uptime >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"

echo. >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
echo ### Command >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% VM.command_line >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"

echo. >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
echo ### Flags >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% VM.flags >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"

echo. >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
echo ### Properties >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% VM.system_properties >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"

%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% Thread.print -l >"%DUMP_DIR%\%PID%-%timestamp%-threads.log"

%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% GC.heap_dump "%DUMP_DIR%\%PID%-%timestamp%-heap.hprof"

echo Dumped to %DUMP_DIR%

จะต้องทำงานในเซสชัน Windows เดียวกันของผู้ใช้ที่เริ่มต้น JVM ดังนั้นหากคุณเชื่อมต่อผ่าน Remote Desktop คุณอาจต้องเปิดใช้งานพรอมต์คำสั่งSession 0และเรียกใช้จากที่นั่น เช่น

%PsExec% -s -h -d -i 0 cmd.exe

สิ่งนี้จะแจ้งให้คุณ (คลิกที่ไอคอนแถบงานที่ด้านล่าง) เพื่อView the messageในเซสชันโต้ตอบซึ่งจะนำคุณไปยังคอนโซลใหม่ในเซสชั่นอื่น ๆ ที่คุณสามารถเรียกใช้jvmdump.batสคริปต์


2

จะรับรหัสกระบวนการของแอพพลิเคชัน Java ได้อย่างไร

ดำเนินการคำสั่ง 'jcmd' เพื่อรับ id กระบวนการของแอ็พพลิเคชัน java

จะรับเธรดการถ่ายโอนข้อมูลได้อย่างไร

jcmd PID Thread.print> thread.dump

ลิงค์อ้างอิง

คุณสามารถใช้ jstack เพื่อรับ thread dump (jstack PID> thread.dump) ลิงค์อ้างอิง

วิธีรับการถ่ายโอนข้อมูลฮีป

ใช้เครื่องมือ jmap เพื่อรับ heap dump jmap -F -dump: live, format = b, file = heap.bin PID

PID ย่อมาจาก id กระบวนการของแอปพลิเคชัน ลิงค์อ้างอิง


1

อาจจะเป็นjcmd ?

Jcmdยูทิลิตีใช้เพื่อส่งคำขอคำสั่งการวินิจฉัยไปยัง JVM ซึ่งการร้องขอเหล่านี้มีประโยชน์สำหรับการควบคุม Java Flight Recordings แก้ไขปัญหาและวินิจฉัย JVM และ Java Applications

เครื่องมือ jcmd ได้รับการแนะนำกับ Java 7 ของ Oracle และมีประโยชน์อย่างยิ่งในการแก้ไขปัญหาเกี่ยวกับแอปพลิเคชัน JVM โดยใช้เพื่อระบุ ID กระบวนการของ Java (คล้ายกับ jps), รับการทิ้งฮีป (คล้ายกับ jmap) ) ดูคุณสมบัติเครื่องเสมือนเช่นคุณสมบัติของระบบและแฟล็กบรรทัดคำสั่ง (akin to jinfo) และการรับสถิติการรวบรวมขยะ (akin to jstat) เครื่องมือ jcmd ถูกเรียกว่า "มีดสวิส - กองทัพสำหรับการตรวจสอบและแก้ไขปัญหาด้วยแอปพลิเคชัน JVM ของคุณ" และ "อัญมณีที่ซ่อนอยู่"

นี่คือกระบวนการที่คุณจะต้องใช้ในการเรียกใช้jcmd:

  1. ไปที่ jcmd <pid> GC.heap_dump <file-path>
  2. ซึ่งใน
  3. pid: เป็นรหัสกระบวนการ Java ซึ่งการถ่ายโอนข้อมูลกองจะถูกจับยัง
  4. file-path: เป็นพา ธ ไฟล์ที่จะพิมพ์ดัมพ์ฮีพ

ตรวจสอบออกสำหรับข้อมูลเพิ่มเติมเกี่ยวกับการถ่ายโอนข้อมูล Java กอง


0

การติดตาม Visualvm:

หากคุณ "ไม่สามารถเชื่อมต่อ" กับ JVM ที่ใช้งานอยู่ของคุณจาก jvisualvm เพราะคุณไม่ได้เริ่มต้นด้วยอาร์กิวเมนต์ JVM ที่ถูกต้อง (และอยู่ในกล่องระยะไกล) ให้เรียกใช้jstatdบนกล่องระยะไกลจากนั้นสมมติว่าคุณมีการเชื่อมต่อโดยตรงเพิ่ม มันเป็น "รีโมตโฮสต์" ใน visualvm คลิกสองครั้งที่ชื่อโฮสต์และ JVM อื่น ๆ ทั้งหมดในกล่องนั้นจะแสดงอย่างน่าอัศจรรย์ใน visualvm

หากคุณไม่ได้มี "การเชื่อมต่อโดยตรง" พอร์ตบนกล่องนั้นคุณยังสามารถทำเช่นนี้ผ่านพร็อกซี่

เมื่อคุณเห็นกระบวนการที่คุณต้องการแล้วให้เจาะเข้าไปใน jvisualvm และใช้แท็บมอนิเตอร์ -> ปุ่ม "heapdump"


0

โค้ด java ด้านล่างใช้เพื่อรับ Heap Dump ของกระบวนการ Java โดยระบุ PID โปรแกรมใช้การเชื่อมต่อ JMX ระยะไกลเพื่อถ่ายโอนข้อมูลกอง มันอาจเป็นประโยชน์สำหรับบางคน

import java.lang.management.ManagementFactory;
import javax.management.MBeanServerConnection;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import java.lang.reflect.Method;

public class HeapDumper {

public static final String HOST = "192.168.11.177";
public static final String PORT = "1600";
public static final String FILE_NAME = "heapDump.hprof";
public static final String FOLDER_PATH = "C:/";
private static final String HOTSPOT_BEAN_NAME ="com.sun.management:type=HotSpotDiagnostic";

public static void main(String[] args) {
    if(args.length == 0) {
        System.out.println("Enter PID of the Java Process !!!");
        return;
    }

    String pidString = args[0];
    int pid = -1;
    if(pidString!=null && pidString.length() > 0) {
        try {
            pid = Integer.parseInt(pidString);
        }
        catch(Exception e) {
            System.out.println("PID is not Valid !!!");
            return;
        }
    }
    boolean isHeapDumpSuccess = false;
    boolean live = true;
    if(pid > 0) {
        MBeanServerConnection beanServerConn = getJMXConnection();

        if(beanServerConn!=null) {
            Class clazz = null;
            String dumpFile = FOLDER_PATH+"/"+FILE_NAME;
            try{
                clazz = Class.forName("com.sun.management.HotSpotDiagnosticMXBean");
                Object hotspotMBean = ManagementFactory.newPlatformMXBeanProxy(beanServerConn, HOTSPOT_BEAN_NAME, clazz);
                Method method = clazz.getMethod("dumpHeap", new Class[]{String.class , boolean.class});
                method.setAccessible(true);
                method.invoke(hotspotMBean , new Object[] {dumpFile, new Boolean(live)});
                isHeapDumpSuccess = true;
            }
            catch(Exception e){
                e.printStackTrace();
                isHeapDumpSuccess = false;
            }
            finally{
                clazz = null;
            }
        }
    }

    if(isHeapDumpSuccess){
        System.out.println("HeapDump is Success !!!");
    }
    else{
        System.out.println("HeapDump is not Success !!!");
    }
}

private static MBeanServerConnection getJMXConnection() {
    MBeanServerConnection mbeanServerConnection = null;
    String urlString = "service:jmx:rmi:///jndi/rmi://" + HOST + ":" + PORT + "/jmxrmi";
    try {
        JMXServiceURL url = new JMXServiceURL(urlString);
        JMXConnector jmxConnector = JMXConnectorFactory.connect(url);
        mbeanServerConnection = jmxConnector.getMBeanServerConnection();
        System.out.println("JMX Connection is Success for the URL :"+urlString);
    }
    catch(Exception e) {
        System.out.println("JMX Connection Failed !!!");
    }
    return mbeanServerConnection;
}

}


0

Inorder ที่จะใช้เธรด dump / heap จากกระบวนการ child java ใน windows คุณต้องระบุ id กระบวนการเด็กเป็นขั้นตอนแรก

โดยการออกคำสั่ง: jpsคุณจะสามารถรับรหัสกระบวนการ java ทั้งหมดที่ทำงานบนเครื่อง windows ของคุณ จากรายการนี้คุณต้องเลือกรหัสกระบวนการลูก เมื่อคุณมีกระบวนการลูกรหัสมีตัวเลือกต่าง ๆ เพื่อจับเธรดการถ่ายโอนข้อมูลและทิ้งกอง

การถ่ายทิ้งกระทู้:

มี 8 ตัวเลือกในการดักจับการทิ้งเธรด:

  1. jstack
  2. kill -3
  3. jvisualVM
  4. JMC
  5. Windows (Ctrl + ตัวแบ่ง)
  6. ThreadMXBean
  7. เครื่องมือ APM
  8. jcmd

รายละเอียดเกี่ยวกับตัวเลือกแต่ละสามารถพบได้ในบทความนี้ เมื่อคุณมีเธรดดัมพ์แล้วคุณสามารถใช้เครื่องมือเช่นfastThread , Samuraito จะวิเคราะห์การดัมพ์ของเธรด

การทิ้งกองฮีป:

มี 7 ตัวเลือกในการดักจับกองขยะ:

  1. jmap

  2. -XX: + HeapDumpOnOutOfMemoryError

  3. jcmd

  4. JVisualVM

  5. JMX

  6. วิธีการโปรแกรม

  7. คอนโซลการบริหาร

รายละเอียดเกี่ยวกับตัวเลือกแต่ละสามารถพบได้ในบทความนี้ เมื่อคุณดักจับการถ่ายโอนข้อมูลฮีปคุณอาจใช้เครื่องมือเช่นเครื่องมือวิเคราะห์หน่วยความจำ Eclipse , HeapHeroเพื่อวิเคราะห์ทิ้งฮีปที่จับ


-1

บน Oracle JDK เรามีคำสั่งชื่อ jmap (มีอยู่ในโฟลเดอร์ bin ของ Java Home) การใช้คำสั่งดังต่อไปนี้

jmap (ตัวเลือก) (pid)

ตัวอย่าง: jmap -dump: live, format = b, file = heap.bin (pid)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.