คุณจะทำ JVM ผิดพลาดได้อย่างไร?


144

ฉันกำลังอ่านหนังสือเกี่ยวกับทักษะการเขียนโปรแกรมที่ผู้เขียนถามผู้สัมภาษณ์ว่า "คุณทำ JVM ผิดพลาดได้อย่างไร" ฉันคิดว่าคุณสามารถทำได้โดยเขียน infinite for-loop ที่จะใช้หน่วยความจำหมด

ใครมีความคิดบ้าง


1
ซูเปอร์เซ็ตที่เป็นไปได้ของ: stackoverflow.com/questions/6470651/ …
Ciro Santilli 法轮功冠状病病六四事件法轮功

stackoverflow.com/questions/30072883/… "ถ้าฉันใช้ JDK1.8_40 หรือใหม่กว่า (Oracle หรือ OpenJDK ทำเช่นเดียวกัน) รหัสต่อไปนี้พร้อมกับการปรับขนาดไดอะล็อกจะขัดข้องแอปพลิเคชัน (ลองใช้ Windows 7, x64, 64 บิต JDK)" - โค้ดมีเพียง 40 บรรทัดและทำให้เกิดความผิดพลาดที่เหมาะสมของ JVM
ประธานาธิบดี Dreamspace

คำตอบ:


6

สิ่งที่ใกล้เคียงที่สุดกับ "คำตอบ" เดียวคือการSystem.exit()ยกเลิก JVM ทันทีโดยไม่มีการล้างข้อมูลที่เหมาะสม แต่นอกเหนือจากนั้นรหัสท้องถิ่นและทรัพยากรที่อ่อนล้าเป็นคำตอบที่เป็นไปได้มากที่สุด อีกทางหนึ่งคุณสามารถดูข้อบกพร่องของ Sun ในการติดตาม JVM ในเวอร์ชันของคุณซึ่งบางสถานการณ์อนุญาตให้ทำซ้ำได้ เราเคยเกิดปัญหาแบบกึ่งปกติเมื่อใกล้ถึงขีด จำกัด หน่วยความจำ 4 Gb ภายใต้รุ่น 32 บิต (โดยทั่วไปเราใช้ 64 บิตในขณะนี้)


71
ไม่มีการทำความสะอาดที่เหมาะสม? คุณแน่ใจไหม? เอกสารอธิบายว่า "ยกเลิกเครื่องเสมือน Java ที่กำลังรันอยู่ในขณะนี้โดยเริ่มต้นลำดับการปิดระบบ ... ตะขอการปิดระบบที่ลงทะเบียนแล้วทั้งหมดจะเริ่มทำงาน ... ตัว finalizers ที่ไม่มีการเรียกใช้ทั้งหมดจะทำงาน" - ไม่ใช่ว่าเป็นการล้างข้อมูลที่เหมาะสมหรือไม่
user85421

51
นี่ไม่ใช่การหยุดทำงานของ JVM แต่เป็นการเริ่มต้นการปิดการทำงานที่เป็นระเบียบและชัดเจน
BenM

9
ใกล้เคียงกับความล้มเหลวของ jvm คือ Runtime.getRuntime (). halt (status) ตามเอกสาร "วิธีนี้ไม่ทำให้ตะขอสำหรับปิดเครื่องเริ่มต้นขึ้นและไม่เรียกใช้ finalizers ที่ไม่ได้เรียกใช้หากเปิดใช้งานการปิดใช้งานขั้นสุดท้ายเมื่อออก" ยังไม่ใช่ความผิดพลาด แต่ใกล้กว่า System.exit
เฮนรี่

48
นี่เป็นคำตอบที่ไม่ดีจริงๆ
อันโตนิโอ

174

ฉันจะไม่เรียกการขว้าง OutOfMemoryError หรือ StackOverflowError นี่เป็นข้อยกเว้นปกติ ในการที่จะชน VM จริงๆมี 3 วิธี:

  1. ใช้ JNI และล้มเหลวในรหัสเนทีฟ
  2. หากไม่มีการติดตั้งตัวจัดการความปลอดภัยคุณสามารถใช้การสะท้อนเพื่อขัดข้อง VM นี่คือ VM ที่เฉพาะเจาะจง แต่โดยปกติแล้ว VM จะจัดเก็บพอยน์เตอร์จำนวนมากไปยังแหล่งข้อมูลดั้งเดิมในเขตข้อมูลส่วนตัว (เช่นตัวชี้ไปยังวัตถุเธรดดั้งเดิมถูกเก็บไว้ในฟิลด์ที่ยาวในjava.lang.Thread ) เพียงแค่เปลี่ยนผ่านการสะท้อนและ VM จะหยุดทำงานไม่ช้าก็เร็ว
  3. VMs ทั้งหมดมีข้อบกพร่องดังนั้นคุณเพียงแค่ต้องเรียกใช้

สำหรับวิธีสุดท้ายฉันมีตัวอย่างสั้น ๆ ซึ่งจะทำให้ Sun Hotspot VM เงียบดี:

public class Crash {
    public static void main(String[] args) {
        Object[] o = null;

        while (true) {
            o = new Object[] {o};
        }
    }
}

สิ่งนี้นำไปสู่การโอเวอร์โฟลว์สแต็กใน GC ดังนั้นคุณจะไม่ได้รับ StackOverflowError แต่เกิดความผิดพลาดจริงรวมถึงไฟล์ hs_err *


9
ว้าว! สิ่งนี้ขัดข้อง Sun Java 5, Sun Java 6 และ OpenJDK 6 (บน Ubuntu 9.04) โดยไม่มีไฟล์ hs_err * แต่มีเพียง "Segmentation fault!" ...
Joachim Sauer

1
System.exit () เป็นวิธีที่ง่ายกว่ามากที่จะทำให้เกิดข้อผิดพลาด JVM (ยกเว้นว่ามีการติดตั้งตัวจัดการความปลอดภัย)
instantsetsuna

4
ไม่ทราบเมื่อแก้ไขแล้ว แต่เพิ่งทดสอบใน 1.7.0_09 และใช้ได้ เพิ่งได้รับสิ่งที่คาดไว้: ข้อยกเว้นในเธรด "main" java.lang.OutOfMemoryError: พื้นที่ว่างของ heap ของ Java ที่ CrashJVM.main (CrashJVM.java:7)
Chad NB

2
ฉันลองรหัสข้างต้นบน Intel Core i7 2.4 GHz / 8 GB RAM / JDK1.7 64 บิต แต่ JVM ยังคงขึ้นหลังจาก 20 นาที (ตลก: แฟนแล็ปท็อปของฉันดังกว่าเจ็ทนักสู้บนท้องฟ้า) ปัญหานี้ได้รับการแก้ไขใน JDK 1.7+ หรือไม่
realPK

3
ใน JDK 1.8_u71 สิ่งนี้ทำให้ ajava.lang.OutOfMemoryError: GC overhead limit exceeded
Clashsoft

124

JNI ในความเป็นจริงด้วย JNI การหยุดทำงานเป็นโหมดเริ่มต้นของการทำงาน คุณต้องทำงานหนักเป็นพิเศษเพื่อที่จะได้ไม่เกิดปัญหา


4
บางทีนักออกแบบของ JNI อาจเคยได้ยินเกี่ยวกับซอฟต์แวร์ที่ทำงานผิดพลาดเท่านั้นแต่ก็ยังไม่เข้าใจความคิดนี้
Tom Anderson

56

ใช้สิ่งนี้:

import sun.misc.Unsafe;

public class Crash {
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    public static void crash() {
        unsafe.putAddress(0, 0);
    }
    public static void main(String[] args) {
        crash();
    }
}

คลาสนี้ต้องอยู่ใน boot classpath เนื่องจากใช้รหัสที่เชื่อถือได้ดังนั้นให้เรียกใช้ดังนี้:

java -Xbootclasspath / p :. ชน


14
แทนที่จะใช้ -Xbootclasspath คุณสามารถทำได้: ใช้งานได้Field f = Unsafe.class.getDeclaredField( "theUnsafe" ); f.setAccessible( true ); unsafe = (Unsafe) f.get( null );ดีสำหรับฉัน
รุก

Unsafeคือโดยคำจำกัดความ "ไม่ปลอดภัย" นี่เป็นบิตของการโกง
Hot Licks

1
การยืนยันการทำงานโดยใช้getDeclaredFieldเคล็ดลับใน JDK 8u131 บน Linux x64 รวมทั้งการผลิตจากhs_err_pid*.log SIGSEGV
Jesse Glick

การใช้Unsafeไม่ใช่การโกง OP ไม่ได้มองหาวิธีการ 'สะอาด' สำหรับปัญหาการเขียนโปรแกรม เขาต้องการ jvm ที่จะผิดพลาดในวิธีที่เป็นไปได้ที่น่าเกลียดที่สุด การทำสิ่งที่น่ารังเกียจในท้องถิ่นคือสิ่งที่สามารถทำให้เกิดขึ้นได้และมันก็เป็นUnsafeเช่นนั้น
jvdneste

34

ฉันมาที่นี่เพราะฉันเจอคำถามนี้ในThe Passionate Programmerโดย Chad Fowler สำหรับผู้ที่ไม่สามารถเข้าถึงสำเนาคำถามจะถูกจัดเรียงเป็นตัวกรอง / การทดสอบสำหรับผู้สมัครสัมภาษณ์ตำแหน่งที่ต้องการ "โปรแกรมเมอร์ Java ที่ดีจริงๆ"

เขาถามว่า:

คุณจะเขียนโปรแกรมในจาวาบริสุทธิ์ที่จะทำให้ Java Virtual Machine พังได้อย่างไร

ฉันตั้งโปรแกรมใน Java มานานกว่า 15 ปีแล้วและฉันพบว่าคำถามนี้น่าสงสัยและไม่ยุติธรรม ขณะที่คนอื่น ๆ ได้ออกมาชี้, Java เป็นภาษาที่มีการจัดการการออกแบบเป็นพิเศษไม่ให้ผิดพลาด แน่นอนว่ามีข้อบกพร่อง JVM อยู่เสมอ แต่:

  1. หลังจาก JREs ระดับการผลิต 15 ปีขึ้นไปมันหายาก
  2. บั๊กดังกล่าวมีแนวโน้มที่จะได้รับการติดตั้งในรีลีสถัดไปดังนั้นคุณมีโอกาสมากแค่ไหนที่โปรแกรมเมอร์ในการเรียกใช้และจดจำรายละเอียดของชุดปัจจุบันของ JRE show-stoppers

ดังที่คนอื่น ๆ ได้กล่าวถึงแล้วโค้ดเนทีฟบางตัวผ่าน JNI เป็นวิธีที่แน่นอนในการทำลาย JRE แต่ผู้เขียนกล่าวถึงเฉพาะใน Java บริสุทธิ์เพื่อให้ออก

ตัวเลือกอื่นคือการป้อนรหัสไบต์ JRE เป็นการหลอกลวง มันง่ายพอที่จะถ่ายโอนข้อมูลไบนารีขยะบางส่วนไปยังไฟล์. class และขอให้ JRE เรียกใช้:

$ echo 'crap crap crap' > crap.class
$ java crap
Exception in thread "main" java.lang.ClassFormatError: Incompatible magic value 1668440432 in class file crap

นั่นนับหรือไม่ ฉันหมายถึงตัว JRE เองไม่ได้ล้มเหลว ตรวจพบรหัสปลอมรายงานและออกอย่างถูกต้อง

ใบนี้เรามีชนิดที่ชัดเจนที่สุดของการแก้ปัญหาเช่นพัดผ่านสแต็ค recursion RuntimeExceptionที่วิ่งออกมาจากหน่วยความจำผ่านการจัดสรรกองวัตถุหรือเพียงแค่การขว้างปา แต่เพียงแค่นี้ทำให้ JRE เพื่อออกด้วยStackOverflowErrorหรือข้อยกเว้นที่คล้ายกันซึ่งอีกไม่ได้จริงๆความผิดพลาด

แล้วมีอะไรเหลืออยู่? ฉันชอบที่จะได้ยินสิ่งที่ผู้เขียนมีอยู่ในใจว่าเป็นทางออกที่เหมาะสม

อัพเดท : แช้ดฟาวเลอร์ตอบที่นี่

PS: มันเป็นหนังสือที่ยอดเยี่ยม ฉันเลือกมันเพื่อการสนับสนุนทางศีลธรรมในขณะที่เรียนรูบี้


1
คำถามสัมภาษณ์ดังกล่าวทำหน้าที่เป็นการทดสอบสารสีน้ำเงินสำหรับนักพัฒนา Java ที่มีมานานพอที่จะ 1) ได้เห็น (หลาย) JVM ล่มและ 2) ได้ข้อสรุปบางอย่างหรือดีกว่า (ผู้เชี่ยวชาญ) Java ได้พยายามทำความเข้าใจ เหตุผลพื้นฐานสำหรับความผิดพลาด แช้ดฟาวเลอร์ยังกล่าวในหนังสือของเขาว่าโปรแกรมเมอร์ Java ที่ประกาศตัวเองว่า "ไม่สามารถคิดคำตอบที่ผิด" ได้นั่นคือยังไม่ได้ลองคิดดูเมื่อปัญหาที่อาจเกิดขึ้นกับทั้งชั้นเรียน บรรทัดล่าง: คำถามนี้คือ segway ถึง "วิธีป้องกัน JVM ล่ม" ซึ่งชัดเจนยิ่งขึ้นกว่าที่จะรู้
Shonzilla

1
ฉันจะมองหาคนที่เพิ่งตอบ (มากที่สุดที่นี่) "ล้นกอง", system.exit () หรือปิด "ปกติ" อื่น ๆ เพราะพวกเขาไม่เข้าใจ JVM หรือคำว่า "ผิดพลาด" จริงๆ การรับรู้ (เช่นเดียวกับคุณ) ว่าสิ่งนี้ผิดปกติมากเป็นวิธีที่ดีในการระบุโปรแกรมเมอร์ที่สูงขึ้น ฉันเห็นด้วยกับข้อความแรกของคุณฉันพบว่ามันเป็นคำถามที่ยอดเยี่ยมและยุติธรรมโดยสมบูรณ์ที่จะถามหรือถามคำถามที่ไม่มีคำตอบที่เป็นรูปธรรมนั้นดีที่สุดเสมอ
Bill K

20

รหัสนี้จะผิดพลาด JVM ในรูปแบบที่น่ารังเกียจ

import sun.dc.pr.PathDasher; 

public class Crash
{
     public static void main(String[] args)
     {    
        PathDasher dasher = new PathDasher(null) ;
     }
}

1
การรวบรวมข้อผิดพลาดเมื่อใช้ JDK 1.7 ด้วยรหัสนี้: ข้อ จำกัด การเข้าถึง: ประเภท PathDasher ไม่สามารถเข้าถึงได้เนื่องจากข้อ จำกัด ในไลบรารีที่ต้องการ C: \ Program Files \ Java \ jdk1.7.0_51 \ jre \ lib \ rt.jar
realPK

7
สิ่งนี้จะเป็นการโยนInternalErrorใน JDK 1.8 JVM ไม่ล้มเหลวอีกต่อไป
Sotirios Delimanolis

18

ครั้งล่าสุดที่ฉันลองทำสิ่งนี้จะทำได้:

public class Recur {
    public static void main(String[] argv) {
        try {
            recur();
        }
        catch (Error e) {
            System.out.println(e.toString());
        }
        System.out.println("Ended normally");
    }
    static void recur() {
        Object[] o = null;
        try {
            while(true) {
                Object[] newO = new Object[1];
                newO[0] = o;
                o = newO;
            }
        }
        finally {
            recur();
        }
    }
}

ส่วนแรกของไฟล์บันทึกที่สร้าง:

#
# An unexpected error has been detected by Java Runtime Environment:
#
#  EXCEPTION_STACK_OVERFLOW (0xc00000fd) at pc=0x000000006dad5c3d, pid=6752, tid=1996
#
# Java VM: Java HotSpot(TM) 64-Bit Server VM (11.2-b01 mixed mode windows-amd64)
# Problematic frame:
# V  [jvm.dll+0x2e5c3d]
#
# If you would like to submit a bug report, please visit:
#   http://java.sun.com/webapps/bugreport/crash.jsp
#

---------------  T H R E A D  ---------------

Current thread (0x00000000014c6000):  VMThread [stack: 0x0000000049810000,0x0000000049910000] [id=1996]

siginfo: ExceptionCode=0xc00000fd, ExceptionInformation=0x0000000000000001 0x0000000049813fe8 

Registers:
EAX=0x000000006dc83090, EBX=0x000000003680f400, ECX=0x0000000005d40ce8, EDX=0x000000003680f400
ESP=0x0000000049813ff0, EBP=0x00000000013f2df0, ESI=0x00000000013f0e40, EDI=0x000000003680f400
EIP=0x000000006dad5c3d, EFLAGS=0x0000000000010206

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

ฉันยอมรับว่า downvote ไม่ได้รับการรับรองนี่เป็นความผิดพลาดที่แท้จริง แต่คุณจะตอบคำถามสัมภาษณ์อย่างไร หากคุณไม่เคยค้นคว้าและจดจำสิ่งนี้มาก่อนคุณไม่สามารถให้คำตอบในการสัมภาษณ์ได้และหากคุณสามารถฉันจะพิจารณาคำตอบที่เป็นกลางและไม่ดี - มันไม่ได้แสดงว่าคุณจะแก้ปัญหาอย่างไร ฉันคาดหวังสิ่งที่คุณทำคือ google สำหรับข้อผิดพลาด jvm และใช้ประโยชน์ซึ่งเป็นคำตอบที่ดี
Bill K

@BillK - ไม่ข้างต้นเป็นงานของฉันทั้งหมดแม้ว่าฉันจะได้รับมันเมื่อหลายปีก่อนโดยทดลองกับสิ่งต่าง ๆ ในการสัมภาษณ์ฉันอาจจะพูดว่า "ฉันทำเสร็จแล้วโดยใช้ลอง / จับและเรียกซ้ำ แต่ตอนนี้ฉันไม่สามารถพูดรหัสที่ถูกต้องได้"
Hot Licks

1
อะไรคือรายละเอียด (รุ่น JDK, อาร์กิวเมนต์ VM ใด ๆ )? ไม่แน่ใจว่ารุ่น "11.2-b0" คืออะไร ฉันกำลังใช้งานอยู่ แต่ใช้ CPU จำนวนมากเท่านั้น
Stefan Reich

@ Hot Licks: แนวคิดในตัวอย่างของความผิดพลาดของ JVM คืออะไร? ทำไม JVM ขัดข้องเกี่ยวกับรหัส เธรดทั้งหมดมีเธรดสแต็กแยกกัน ...
VJS

15

การใช้ JVM ที่สมบูรณ์แบบจะไม่ผิดพลาด

ในการหยุด JVM นอกเหนือจาก JNI คุณจะต้องค้นหาข้อบกพร่องใน VM เอง การวนซ้ำไม่สิ้นสุดใช้งาน CPU เพียงอย่างเดียว การจัดสรรหน่วยความจำอย่างไม่ จำกัด ควรทำให้ OutOfMemoryError อยู่ใน JVM ที่สร้างขึ้นมาอย่างดี นี่อาจเป็นสาเหตุของปัญหาสำหรับเธรดอื่น แต่ JVM ที่ดียังคงไม่ควรผิดพลาด

หากคุณพบข้อผิดพลาดในซอร์สโค้ดของ VM และตัวอย่างเช่นทำให้เกิดข้อผิดพลาดในการแบ่งเซกเมนต์ในการใช้หน่วยความจำของการใช้งานของ VM ดังนั้นคุณสามารถผิดพลาดได้จริง


14

หากคุณต้องการที่จะพัง JVM - ใช้สิ่งต่อไปนี้ใน Sun JDK 1.6_23 หรือต่ำกว่า:

Double.parseDouble("2.2250738585072012e-308");

นี่เป็นเพราะข้อผิดพลาดใน Sun JDK - พบได้ใน OpenJDK สิ่งนี้ได้รับการแก้ไขจาก Oracle JDK 1.6_24 เป็นต้นไป


10

ขึ้นอยู่กับสิ่งที่คุณหมายถึงโดยผิดพลาด

คุณสามารถทำการวนซ้ำแบบไม่มีที่สิ้นสุดเพื่อทำให้พื้นที่สแต็กหมด แต่มันจะพัง "อย่างสง่างาม" คุณจะได้รับข้อยกเว้น แต่ JVM เองจะจัดการทุกอย่าง

คุณยังสามารถใช้ JNI เพื่อโทรหารหัสเนทีฟ หากคุณไม่ทำมันอย่างถูกต้องคุณสามารถทำให้มันพังได้ยาก การดีบักข้อผิดพลาดเหล่านั้นคือ "สนุก" (เชื่อฉันฉันต้องเขียน C ++ DLL ตัวใหญ่ที่เราเรียกจากแอปเพล็ต java ที่ลงชื่อแล้ว) :)


6

หนังสือJava Virtual Machineโดย Jon Meyer มีตัวอย่างของชุดคำสั่ง bytecode ที่ทำให้ JVM เป็น core dump ฉันหาสำเนาของหนังสือเล่มนี้ไม่พบ หากมีใครมีกรุณาค้นหาและโพสต์คำตอบ


5

บน winxpsp2 w / wmp10 jre6.0_7

Desktop.open (uriToAviOrMpgFile)

ซึ่งทำให้เธรด spawned เพื่อโยน Throwable ที่ไม่ถูกตรวจจับและหยุดฮอตสปอต

YMMV


5

ฮาร์ดแวร์ที่ใช้งานไม่ได้อาจมีปัญหาโปรแกรมใด ๆ ฉันเคยมีปัญหาแอพที่ทำซ้ำบนเครื่องเฉพาะในขณะที่ทำงานได้ดีบนเครื่องอื่นด้วยการตั้งค่าเดียวกัน ปรากฎว่าเครื่องมี RAM ผิดพลาด


5

วิธีที่สั้นที่สุด :)

public class Crash
{
    public static void main(String[] args)
    {
        main(args);
    }
}

ไม่ผิดพลาด Exception in thread "main" java.lang.StackOverflowError at Test.mainมันทำให้ผิดพลาดเวลารวบรวม ฉันใช้ jdk1.8.0_65
Quazi Irfan

5

ไม่ใช่ความผิดพลาด แต่ใกล้เคียงกับความผิดพลาดมากกว่าคำตอบที่ยอมรับจากการใช้ System.exit

คุณสามารถหยุด JVM ได้โดยโทร

Runtime.getRuntime().halt( status )

ตามเอกสาร: -

msgstr "วิธีนี้ไม่ทำให้ตะขอสำหรับปิดเครื่องเริ่มต้นขึ้นและไม่เรียกใช้ตัวปิดการทำงานที่ไม่ได้เรียกใช้หากการเปิดใช้งานขั้นสุดท้ายเมื่อออก"



4

หากคุณต้องการเสแสร้งว่าคุณมีหน่วยความจำไม่เพียงพอคุณสามารถทำได้

public static void main(String[] args) {
    throw new OutOfmemoryError();
}

ฉันรู้วิธีทำให้ JVM ดัมพ์ไฟล์ข้อผิดพลาดสองวิธีโดยการเรียกเมธอดดั้งเดิม (ที่ถูกสร้างขึ้น) แต่อาจเป็นวิธีที่ดีที่สุดที่คุณไม่ทราบวิธีการทำเช่นนี้ ;)


4

หากคุณกำหนดความผิดพลาดเป็นกระบวนการยกเลิกเนื่องจากสถานการณ์ที่ไม่สามารถจัดการได้ (เช่นไม่มีข้อยกเว้นของ Java หรือข้อผิดพลาด) ดังนั้นจึงไม่สามารถทำได้จากภายใน Java (เว้นแต่คุณจะได้รับอนุญาตให้ใช้คลาส sun.misc.Unsafe) นี่คือจุดทั้งหมดของรหัสที่ได้รับการจัดการ

ความผิดพลาดทั่วไปในโค้ดเนทีฟเกิดขึ้นโดยการพอยน์เตอร์อ้างอิงไปยังพื้นที่หน่วยความจำผิด (ที่อยู่ว่างหรือพลาด) แหล่งอื่นอาจเป็นคำสั่งเครื่องที่ผิดกฎหมาย (opcodes) หรือสัญญาณที่ไม่สามารถจัดการได้จากการเรียกใช้ไลบรารีหรือเคอร์เนล ทั้งสองสามารถถูกเรียกใช้หาก JVM หรือไลบรารีระบบมีข้อบกพร่อง

ตัวอย่างเช่นรหัส JITed (สร้างขึ้น) วิธีดั้งเดิมหรือการเรียกของระบบ (ไดรเวอร์กราฟิก) อาจมีปัญหาที่ทำให้เกิดปัญหาจริง (เป็นเรื่องปกติที่จะเกิดความผิดพลาดเมื่อคุณใช้ฟังก์ชั่น ZIP และหน่วยความจำหมด) ในกรณีดังกล่าวตัวจัดการความผิดพลาดของ JVM จะเริ่มต้นและทิ้งสถานะ มันยังสามารถสร้างไฟล์ core OS (Dr. Watson บน Windows และ core dump บน * nix)

บน Linux / Unix คุณสามารถทำให้ JVM พังได้ง่ายโดยส่งสัญญาณไปยังกระบวนการที่กำลังทำงานอยู่ หมายเหตุ: คุณไม่ควรใช้SIGSEGVสิ่งนี้เนื่องจาก Hotspot จับสัญญาณนี้และโยนมันเป็น NullPointerException ในสถานที่ส่วนใหญ่ ดังนั้นจะเป็นการดีกว่าถ้าส่งSIGBUSตัวอย่าง


3

JNI เป็นแหล่งของการขัดข้องขนาดใหญ่ คุณสามารถผิดพลาดโดยใช้อินเตอร์เฟส JVMTI เนื่องจากต้องเขียนใน C / C ++ เช่นกัน


2

หากคุณสร้างกระบวนการของเธรดที่วางไข่เธรดได้ไม่ จำกัด (ซึ่งจะสร้างเธรดเพิ่มเติมซึ่ง ... ) ในที่สุดคุณจะทำให้เกิดข้อผิดพลาดสแต็กล้นใน JVM เอง

public class Crash {
    public static void main(String[] args) {

        Runnable[] arr = new Runnable[1];
        arr[0] = () -> {

            while (true) {
                new Thread(arr[0]).start();
            }
        };

        arr[0].run();
    }
}

สิ่งนี้ทำให้ฉันออก (หลังจาก 5 นาทีดู ram ของคุณ)

An unrecoverable stack overflow has occurred.
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_STACK_OVERFLOW (0xc00000fd) at pc=0x0000000070e53ed7, pid=12840, tid=0x0000000000101078
#
# JRE version: Java(TM) SE Runtime Environment (8.0_144-b01) (build 1.8.0_144-b01)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.144-b01 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# 

1

หากโดย "crash" คุณหมายถึงการยกเลิก JVM อย่างกระทันหันเช่นจะทำให้ JVM เขียนลงใน hs_err_pid% p.logมันคุณสามารถทำได้ด้วยวิธีนี้

ตั้งค่า -Xmx arg เป็นค่าเล็ก ๆ และบอก JVM เพื่อบังคับให้เกิดความผิดพลาดใน outofmemory:

 -Xmx10m -XX:+CrashOnOutOfMemoryError

เพื่อให้ชัดเจนโดยไม่มีอาร์กิวเมนต์ที่สองข้างต้นก็จะส่งผลให้ jvm ยุติด้วย OutOfMemoryError แต่มันจะไม่ "ผิดพลาด" หรือยกเลิก jvm ทันที

เทคนิคนี้พิสูจน์แล้วว่ามีประโยชน์เมื่อฉันพยายามทดสอบ JVM -XX: ErrorFile arg ซึ่งควบคุมตำแหน่งที่ควรเขียนบันทึก hs_err_pid ฉันได้พบโพสต์นี้ที่นี่ในขณะที่พยายามหาวิธีที่จะบังคับความผิดพลาดดังกล่าว เมื่อภายหลังฉันพบว่าการทำงานข้างต้นเป็นวิธีที่ง่ายที่สุดสำหรับความต้องการของฉันฉันต้องการเพิ่มลงในรายการที่นี่

ท้ายที่สุด FWIW หากใครก็ตามสามารถทดสอบสิ่งนี้เมื่อพวกเขามีค่า -Xms ที่ตั้งค่าไว้ใน args ของคุณ (เป็นค่าที่สูงกว่าบางส่วนด้านบน) คุณจะต้องลบหรือเปลี่ยนแปลงสิ่งนั้นหรือคุณจะไม่ผิดพลาด แต่เพียง ความล้มเหลวในการเริ่มต้น jvm โดยรายงาน "ขนาดฮีพเริ่มต้นที่ตั้งเป็นค่าที่ใหญ่กว่าขนาดฮีพสูงสุด" (นั่นจะไม่ชัดเจนหากใช้ JVM เป็นบริการเช่นกับแอพเซิร์ฟเวอร์บางตัวอีกครั้งมันกัดฉันดังนั้นฉันจึงต้องการแบ่งปันมัน)


0

หากคุณเปลี่ยน infinite สำหรับลูปเป็นการเรียกซ้ำไปยังฟังก์ชันเดียวกันคุณจะได้รับข้อยกเว้นสแต็กโอเวอร์โฟลว์:

public static void main(String[] args) {
    causeStackOverflow();
}

public void causeStackOverflow() {
    causeStackOverflow();
}

0

ตอนนี้ฉันกำลังทำอยู่ แต่ไม่แน่ใจทั้งหมดว่า ... :-) JVM (และแอปของฉัน) บางครั้งก็หายไปอย่างสมบูรณ์ ไม่มีข้อผิดพลาดเกิดขึ้นไม่มีการบันทึก เปลี่ยนจากการทำงานเป็นไม่ทำงานทันทีโดยไม่มีการเตือน


เริ่มตรวจสอบฮาร์ดแวร์ของคุณโดยเฉพาะอย่างยิ่งความจำของคุณ!
Thorbjørn Ravn Andersen

น่าเสียดายที่มันมีหลายเครื่องที่ใช้งานได้ดี มันเป็นเพียงแอพพลิเคชั่นเดียวที่ใช้งานได้ (และไม่ใช่หน่วยความจำหรือตัวประมวลผลที่เข้มข้น)
Brian Knoblauch

0

ที่สั้นที่สุด? ใช้คลาส Robot เพื่อเรียกใช้ CTRL + BREAK ฉันพบสิ่งนี้เมื่อฉันพยายามปิดโปรแกรมโดยไม่ปิดคอนโซล (ไม่มีฟังก์ชัน 'ออก')


คำถามเก่า - หวังว่าใครบางคนจะได้ประโยชน์จากคำตอบของคุณในอนาคต
dbmitch

0

สิ่งนี้นับหรือไม่

long pid = ProcessHandle.current().pid();
try { Runtime.getRuntime().exec("kill -9 "+pid); } catch (Exception e) {}

ใช้งานได้กับ Linux และจาก Java 9 เท่านั้น

ด้วยเหตุผลบางอย่างผมไม่ได้รับProcessHandle.current().destroyForcibly();ไม่ได้ฆ่า JVM และพ่นjava.lang.IllegalStateExceptionด้วยข้อความทำลายของกระบวนการปัจจุบันไม่ได้รับอนุญาต


0

พบปัญหานี้เมื่อพยายามทำซ้ำความผิดพลาดของ JVM

Jni ทำงานได้ แต่ต้องได้รับการปรับแต่งสำหรับแพลตฟอร์มที่แตกต่างกัน ในที่สุดฉันใช้ชุดค่าผสมนี้เพื่อทำให้ JVM หยุดทำงาน

  1. เริ่มแอปพลิเคชันด้วยตัวเลือก JVM นี้ -XX:+CrashOnOutOfMemoryError
  2. ใช้ a long[] l = new long[Integer.MAX_VALUE];เพื่อทริกเกอร์ OOM

จากนั้น JVM จะหยุดทำงานและสร้างบันทึกการทำงานล้มเหลว


-2

หาก 'Crash' คือสิ่งใดก็ตามที่ขัดจังหวะ jvm / โปรแกรมจากการยกเลิกตามปกติแสดงว่าข้อยกเว้น Un-handling สามารถทำสิ่งนี้ได้

public static void main(String args[]){
   int i = 1/0;
   System.out.print(i); // This part will not be executed due to above  unhandled exception
  }

ดังนั้นมันขึ้นอยู่กับ CRASH ประเภทใด!


3
การโยนข้อยกเว้นไม่ใช่ความผิดพลาด
Quazi Irfan

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