เป็นไปได้ไหมที่จะสร้างส่วนของโค้ดในJavaที่จะทำให้ไม่สามารถจับสมมุติฐานได้java.lang.ChuckNorrisException?
ความคิดที่อยู่ในใจคือการใช้ตัวอย่างเช่นตัวดักหรือการเขียนโปรแกรมเชิงกว้าง
finalize()?
                เป็นไปได้ไหมที่จะสร้างส่วนของโค้ดในJavaที่จะทำให้ไม่สามารถจับสมมุติฐานได้java.lang.ChuckNorrisException?
ความคิดที่อยู่ในใจคือการใช้ตัวอย่างเช่นตัวดักหรือการเขียนโปรแกรมเชิงกว้าง
finalize()?
                คำตอบ:
ฉันไม่ได้พยายามนี้ดังนั้นผมจึงไม่ทราบว่าJVMจะ จำกัด บางอย่างเช่นนี้ แต่บางทีคุณอาจจะรวบรวมรหัสที่พ่นChuckNorrisExceptionแต่ที่รันไทม์ให้กำหนดระดับของการChuckNorrisExceptionที่ไม่ขยาย Throwable
UPDATE:
มันไม่ทำงาน มันสร้างข้อผิดพลาดการตรวจสอบ:
Exception in thread "main" java.lang.VerifyError: (class: TestThrow, method: ma\
in signature: ([Ljava/lang/String;)V) Can only throw Throwable objects
Could not find the main class: TestThrow.  Program will exit.
อัปเดต 2:
ที่จริงแล้วคุณสามารถทำให้มันใช้งานได้หากคุณปิดการใช้งานตัวตรวจสอบรหัสไบต์! ( -Xverify:none)
อัปเดต 3:
สำหรับผู้ที่ติดตามจากที่บ้านนี่คือสคริปต์เต็ม
สร้างคลาสต่อไปนี้:
public class ChuckNorrisException
    extends RuntimeException // <- Comment out this line on second compilation
{
    public ChuckNorrisException() { }
}
public class TestVillain {
    public static void main(String[] args) {
        try {
            throw new ChuckNorrisException();
        }
        catch(Throwable t) {
            System.out.println("Gotcha!");
        }
        finally {
            System.out.println("The end.");
        }
    }
}
รวบรวมคลาส:
javac -cp . TestVillain.java ChuckNorrisException.java
วิ่ง:
java -cp . TestVillain
Gotcha!
The end.
ความคิดเห็นที่ "ขยาย RuntimeException" และคอมไพล์ใหม่ChuckNorrisException.javaเท่านั้น :
javac -cp . ChuckNorrisException.java
วิ่ง:
java -cp . TestVillain
Exception in thread "main" java.lang.VerifyError: (class: TestVillain, method: main signature: ([Ljava/lang/String;)V) Can only throw Throwable objects
Could not find the main class: TestVillain.  Program will exit.
ทำงานโดยไม่มีการยืนยัน:
java -Xverify:none -cp . TestVillain
The end.
Exception in thread "main"
              ObjectแทนThrowableแล้ว? (คอมไพเลอร์จะไม่อนุญาต แต่เนื่องจากเราได้ปิดการใช้งานตัวตรวจสอบแล้วอาจมีใครสามารถแฮ็กรหัส bytecode ได้)
                    หลังจากไตร่ตรองสิ่งนี้แล้วฉันได้สร้างข้อยกเว้นที่ไม่สามารถจับตาดูได้สำเร็จ ฉันเลือกที่จะตั้งชื่อมันJulesWinnfieldแทน Chuck เพราะมันเป็นหนึ่งในข้อยกเว้นการวางไข่ของเห็ดเมฆ ยิ่งไปกว่านั้นมันอาจจะไม่ใช่สิ่งที่คุณคิดไว้ในใจ แต่ก็ไม่สามารถจับได้ สังเกต:
public static class JulesWinnfield extends Exception
{
    JulesWinnfield()
    {
        System.err.println("Say 'What' again! I dare you! I double dare you!");
        System.exit(25-17); // And you shall know I am the LORD
    }
}
public static void main(String[] args)
{       
    try
    {
        throw new JulesWinnfield();
    } 
    catch(JulesWinnfield jw)
    {
        System.out.println("There's a word for that Jules - a bum");
    }
}
และ voila! ข้อยกเว้นที่ไม่ได้อ่าน
เอาท์พุท:
วิ่ง:
พูดว่า 'อะไร' อีกครั้ง! ฉันท้าคุณ! ฉันสองครั้งที่กล้าคุณ!
ผล Java: 8
สร้างความสำเร็จ (เวลาทั้งหมด: 0 วินาที)
เมื่อฉันมีเวลาเพิ่มอีกนิดฉันจะดูว่าฉันไม่สามารถคิดเรื่องอื่นได้หรือไม่
นอกจากนี้ตรวจสอบนี้:
public static class JulesWinnfield extends Exception
{
    JulesWinnfield() throws JulesWinnfield, VincentVega
    {
        throw new VincentVega();
    }
}
public static class VincentVega extends Exception
{
    VincentVega() throws JulesWinnfield, VincentVega
    {
        throw new JulesWinnfield();
    }
}
public static void main(String[] args) throws VincentVega
{
    try
    {
        throw new JulesWinnfield();
    }
    catch(JulesWinnfield jw)
    {
    }
    catch(VincentVega vv)
    {
    }
}
ทำให้เกิดการล้นสแต็ก - อีกครั้งข้อยกเว้นยังคงไม่ถูกตรวจสอบ
JulesWinfieldอย่างไร ระบบจะไม่หยุดร้องเสียงกรี๊ดก่อนที่มันจะถูกโยนทิ้ง?
                    throw new Whatever()นั้นมีสองส่วน: Whatever it = new Whatever(); throw it;และระบบจะตายก่อนที่จะถึงส่วนที่สอง
                    class cn extends exception{private cn(){}}
                    ด้วยข้อยกเว้นดังกล่าวมันจะเห็นได้ชัดว่าจำเป็นต้องใช้ a System.exit(Integer.MIN_VALUE);จากนวกรรมิกเพราะนี่คือสิ่งที่จะเกิดขึ้นถ้าคุณโยนข้อยกเว้นเช่น;)
while(true){} System.exit()
                    System.exit()ทำงานโดยการติดตั้งตัวจัดการความปลอดภัยซึ่งไม่อนุญาต ที่จะเปลี่ยน Constructor ให้เป็นข้อยกเว้นอื่น (SecurityException) ซึ่งสามารถตรวจจับได้
                    รหัสใด ๆ ที่สามารถจับได้ Throwable ดังนั้นไม่มีข้อยกเว้นใด ๆ ที่คุณสร้างขึ้นจะเป็นประเภทย่อยของ Throwable และจะถูกจับได้
hangพยายามที่จะจับ ChuckNorrisException: P
                    public class ChuckNorrisException extends Exception {
    public ChuckNorrisException() {
        System.exit(1);
    }
}
(จริงอยู่ที่ข้อยกเว้นทางเทคนิคนี้จะไม่ถูกโยนลงไป แต่ChuckNorrisExceptionจะไม่สามารถโยนทิ้งได้ แต่จะเป็นการโยนคุณก่อน)
ข้อยกเว้นใด ๆ ที่คุณโยนจะต้องขยาย Throwable ดังนั้นจึงสามารถจับได้เสมอ ดังนั้นคำตอบคือไม่
หากคุณต้องการที่จะทำให้มันยากที่จะจัดการคุณสามารถแทนที่วิธีการgetCause(), getMessage(), getStackTrace(), ที่จะโยนอีกtoString()java.lang.ChuckNorrisException
catch(Throwable t)ร้านค้าเพียงลงในตัวแปรเพื่อให้ข้อเสนอแนะของฉันเท่านั้นนำไปใช้ในบล็อกถัดไปเมื่อผู้ใช้ต้องการที่จะรับมือกับการยกเว้น
                    คำตอบของฉันอยู่บนพื้นฐานของความคิด @ jtahlborn แต่ก็ทำงานอย่างเต็มที่Javaโปรแกรมที่สามารถบรรจุลงในJARไฟล์และนำไปใช้กับแอพพลิเคชันเซิร์ฟเวอร์ที่คุณชื่นชอบเป็นส่วนหนึ่งของแม้โปรแกรมประยุกต์บนเว็บ
ก่อนอื่นเรามากำหนดChuckNorrisExceptionคลาสเพื่อไม่ให้ JVM ผิดพลาดตั้งแต่เริ่มต้น (Chuck ชอบการพัง JVMs BTW :)
package chuck;
import java.io.PrintStream;
import java.io.PrintWriter;
public class ChuckNorrisException extends Exception {
    public ChuckNorrisException() {
    }
    @Override
    public Throwable getCause() {
        return null;
    }
    @Override
    public String getMessage() {
        return toString();
    }
    @Override
    public void printStackTrace(PrintWriter s) {
        super.printStackTrace(s);
    }
    @Override
    public void printStackTrace(PrintStream s) {
        super.printStackTrace(s);
    }
}
ตอนนี้ไปExpendablesเรียนเพื่อสร้างมัน:
package chuck;
import javassist.*;
public class Expendables {
    private static Class clz;
    public static ChuckNorrisException getChuck() {
        try {
            if (clz == null) {
                ClassPool pool = ClassPool.getDefault();
                CtClass cc = pool.get("chuck.ChuckNorrisException");
                cc.setSuperclass(pool.get("java.lang.Object"));
                clz = cc.toClass();
            }
            return (ChuckNorrisException)clz.newInstance();
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }
}
และในที่สุดMainชั้นก็เตะก้น:
package chuck;
public class Main {
    public void roundhouseKick() throws Exception {
        throw Expendables.getChuck();
    }
    public void foo() {
        try {
            roundhouseKick();
        } catch (Throwable ex) {
            System.out.println("Caught " + ex.toString());
        }
    }
    public static void main(String[] args) {
        try {
            System.out.println("before");
            new Main().foo();
            System.out.println("after");
        } finally {
            System.out.println("finally");
        }
    }
}
รวบรวมและเรียกใช้ด้วยคำสั่งดังต่อไปนี้:
java -Xverify:none -cp .:<path_to_javassist-3.9.0.GA.jar> chuck.Main
คุณจะได้รับผลลัพธ์ต่อไปนี้:
before
finally
ไม่แปลกใจเลยว่ามันเป็นการเตะแบบวงกว้าง :)
ใน Constructor คุณสามารถเริ่มหัวข้อซึ่งเรียกซ้ำ ๆ originalThread.stop (ChuckNorisException.this) 
ด้ายสามารถจับข้อยกเว้นซ้ำ ๆ แต่จะยังคงขว้างมันจนกว่าจะตาย
ไม่ได้ข้อยกเว้นทั้งหมดใน Java ต้องเป็นคลาสย่อยjava.lang.Throwableและถึงแม้ว่ามันอาจจะไม่ใช่แนวปฏิบัติที่ดี แต่คุณสามารถตรวจสอบข้อยกเว้นทุกประเภทได้เช่น:
try {
    //Stuff
} catch ( Throwable T ){
    //Doesn't matter what it was, I caught it.
}
ดูเอกสารประกอบjava.lang.Throwableสำหรับข้อมูลเพิ่มเติม
หากคุณพยายามหลีกเลี่ยงข้อยกเว้นที่เลือก (สิ่งที่ต้องได้รับการจัดการอย่างชัดเจน) คุณจะต้องการข้อผิดพลาดระดับรองหรือ RuntimeException
จริงๆแล้วคำตอบที่ยอมรับนั้นไม่ค่อยดีนักเพราะจาวาต้องทำงานโดยไม่มีการยืนยันเช่นรหัสจะไม่ทำงานภายใต้สถานการณ์ปกติ
AspectJ เพื่อช่วยเหลือสำหรับทางออกที่แท้จริง !
คลาสข้อยกเว้น:
package de.scrum_master.app;
public class ChuckNorrisException extends RuntimeException {
    public ChuckNorrisException(String message) {
        super(message);
    }
}
มุมมอง:
package de.scrum_master.aspect;
import de.scrum_master.app.ChuckNorrisException;
public aspect ChuckNorrisAspect {
    before(ChuckNorrisException chuck) : handler(*) && args(chuck) {
        System.out.println("Somebody is trying to catch Chuck Norris - LOL!");
        throw chuck;
    }
}
แอปพลิเคชันตัวอย่าง:
package de.scrum_master.app;
public class Application {
    public static void main(String[] args) {
        catchAllMethod();
    }
    private static void catchAllMethod() {
        try {
            exceptionThrowingMethod();
        }
        catch (Throwable t) {
            System.out.println("Gotcha, " + t.getClass().getSimpleName() + "!");
        }
    }
    private static void exceptionThrowingMethod() {
        throw new ChuckNorrisException("Catch me if you can!");
    }
}
เอาท์พุท:
Somebody is trying to catch Chuck Norris - LOL!
Exception in thread "main" de.scrum_master.app.ChuckNorrisException: Catch me if you can!
    at de.scrum_master.app.Application.exceptionThrowingMethod(Application.java:18)
    at de.scrum_master.app.Application.catchAllMethod(Application.java:10)
    at de.scrum_master.app.Application.main(Application.java:5)
              ตัวแปรในชุดรูปแบบเป็นข้อเท็จจริงที่น่าประหลาดใจที่คุณสามารถโยนข้อยกเว้นที่ไม่ได้ประกาศและตรวจสอบได้จากโค้ด Java เนื่องจากไม่ได้ประกาศในลายเซ็นเมธอดเมธอดคอมไพเลอร์จะไม่ยอมให้คุณตรวจจับข้อยกเว้นเองแม้ว่าคุณจะสามารถจับมันเป็น java.lang.Exception
นี่คือคลาสตัวช่วยที่อนุญาตให้คุณโยนอะไรก็ได้ประกาศหรือไม่:
public class SneakyThrow {
  public static RuntimeException sneak(Throwable t) {
    throw SneakyThrow.<RuntimeException> throwGivenThrowable(t);
  }
  private static <T extends Throwable> RuntimeException throwGivenThrowable(Throwable t) throws T {
    throw (T) t;
  }
}
ตอนนี้throw SneakyThrow.sneak(new ChuckNorrisException());จะโยน ChuckNorrisException แต่คอมไพเลอร์บ่นมา
try {
  throw SneakyThrow.sneak(new ChuckNorrisException());
} catch (ChuckNorrisException e) {
}
เกี่ยวกับการจับข้อยกเว้นที่ไม่ได้ถูกโยนหาก ChuckNorrisException เป็นข้อยกเว้นที่ตรวจสอบ
เพียงChuckNorrisExceptionใน Java ควรจะเป็นและOutOfMemoryErrorStackOverflowError
จริงๆคุณสามารถ "จับ" พวกเขาในวิธีที่catch(OutOfMemoryError ex)จะดำเนินการในกรณีที่มีข้อยกเว้นจะถูกโยน แต่บล็อกนั้นจะ rethrow ข้อยกเว้นให้กับผู้โทรโดยอัตโนมัติ
ฉันไม่คิดว่านั่นpublic class ChuckNorrisError extends Errorเป็นการหลอกลวง แต่คุณสามารถลองดูได้ ฉันไม่พบเอกสารเกี่ยวกับการขยายError
Is it possible to construct a snippet of code in java that would make a hypothetical java.lang.ChuckNorrisException uncatchable?
ใช่และนี่คือคำตอบ: การออกแบบของคุณดังกล่าวว่ามันไม่ได้เป็นตัวอย่างของjava.lang.ChuckNorrisException java.lang.Throwableทำไม? วัตถุที่ไม่สามารถถอนได้นั้นไม่สามารถจับได้โดยการกำหนดเพราะคุณไม่สามารถจับอะไรที่ไม่เคยถูกโยนทิ้ง
java.lang.ChuckNorrisExceptionจะต้องเป็นข้อยกเว้นปล่อยให้อยู่คนเดียว
                    คุณสามารถให้ ChuckNorris เป็นส่วนตัวหรือเป็นส่วนตัวและซ่อนเขาหรือตามเขาไป ...
try { doChuckAction(); } catch(ChuckNorrisException cne) { /*do something else*/ }
ปัญหาพื้นฐานสองประการที่มีการจัดการข้อยกเว้นใน Java คือมันใช้ประเภทของข้อยกเว้นเพื่อระบุว่าควรดำเนินการตามหรือไม่และสิ่งใดก็ตามที่ดำเนินการตามข้อยกเว้น (เช่น "catch" es it) จะถูกสันนิษฐานเพื่อแก้ไข เงื่อนไขพื้นฐาน มันจะมีประโยชน์ที่จะมีวิธีการที่วัตถุข้อยกเว้นสามารถตัดสินใจว่าตัวจัดการที่ควรดำเนินการและไม่ว่าตัวจัดการที่ได้ดำเนินการจนถึงขณะนี้มีการทำความสะอาดสิ่งต่าง ๆ เพียงพอสำหรับวิธีการปัจจุบันเพื่อตอบสนองเงื่อนไขการออก ในขณะที่สิ่งนี้สามารถนำมาใช้เพื่อสร้างข้อยกเว้น "ที่ไม่สามารถจับตาดูได้" แต่การใช้ที่ใหญ่กว่าสองประการคือ (1) สร้างข้อยกเว้นที่จะได้รับการพิจารณาเมื่อจัดการด้วยรหัสที่รู้วิธีจัดการกับพวกเขาจริง ๆfinallyFooExceptionระหว่างfinallyบล็อกในระหว่างการคลี่คลายของ a BarException, ข้อยกเว้นทั้งสองควรเผยแพร่สายสแต็ค; ทั้งสองควรจับได้ แต่ไม่ควรคลี่คลายจนกว่าจะถูกจับได้ทั้งคู่) น่าเสียดายที่ฉันไม่คิดว่าจะมีวิธีใดที่จะทำให้โค้ดการจัดการข้อยกเว้นที่มีอยู่ใช้งานได้โดยไม่ทำให้เกิดความเสียหาย
finallyบล็อกกำลังล้างข้อมูลจากข้อยกเว้นก่อนหน้านี้ค่อนข้างเป็นไปได้ว่าอาจมีข้อยกเว้นอย่างใดอย่างหนึ่งในกรณีที่ไม่มีข้อยกเว้นอื่น ๆ แต่การจัดการอย่างใดอย่างหนึ่งและการเพิกเฉยอีกฝ่ายนั้นจะไม่ดี แม้ว่าจะไม่มีกลไกในการสร้างข้อยกเว้นแบบคอมโพสิตที่ตัวจัดการทั้งสองจะประมวลผล
                    Fooสามารถแยกความแตกต่างระหว่างข้อยกเว้นที่Fooทั้งตัวเองโยนหรือจงใจต้องการแกล้งมันตัวเองจากสิ่งที่Fooไม่ได้คาดหวังว่าจะเกิดขึ้นเมื่อมัน เรียกวิธีอื่น นั่นคือสิ่งที่ความคิดของข้อยกเว้น "ตรวจสอบ" ควรเป็น "เกี่ยวกับ"
                    เป็นไปได้อย่างง่ายดายที่จะจำลองข้อยกเว้นที่ไม่ได้ตรวจสอบบนเธรดปัจจุบัน สิ่งนี้จะทริกเกอร์พฤติกรรมปกติของข้อยกเว้นที่ไม่ถูกตรวจจับและทำให้งานสำเร็จตามความหมาย อย่างไรก็ตามจะไม่จำเป็นต้องหยุดการดำเนินการของเธรดปัจจุบันเนื่องจากจะไม่มีข้อยกเว้นเกิดขึ้นจริง
Throwable exception = /* ... */;
Thread currentThread = Thread.currentThread();
Thread.UncaughtExceptionHandler uncaughtExceptionHandler =
    currentThread.getUncaughtExceptionHandler();
uncaughtExceptionHandler.uncaughtException(currentThread, exception);
// May be reachable, depending on the uncaught exception handler.
นี้จะเป็นประโยชน์จริงในการ (หายากมาก) สถานการณ์เช่นเมื่อที่เหมาะสมErrorในการจัดการที่จำเป็น แต่วิธีการที่จะเรียกจากกรอบจับ (และทิ้ง) Throwableใด ๆ
เรียกใช้ System.exit (1) ในfinalizeและเพียงแค่คัดลอกข้อยกเว้นจากวิธีอื่นทั้งหมดเพื่อให้โปรแกรมออกจาก