java - Uncatchable ChuckNorrisException




exception-handling aop (12)

क्या Java में कोड का स्निपेट बनाना संभव है जो एक काल्पनिक java.lang.ChuckNorrisException अचूक बना देगा?

विचार जो दिमाग में आए थे उदाहरण के लिए इंटरसेप्टर या पहलू उन्मुख प्रोग्रामिंग का उपयोग कर रहे हैं।


असल में स्वीकृत उत्तर इतना अच्छा नहीं है क्योंकि जावा को सत्यापन के बिना चलाने की जरूरत है, यानी कोड सामान्य परिस्थितियों में काम नहीं करेगा।

असली समाधान के लिए बचाव के लिए 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)

आप चकनॉरिस को आंतरिक या निजी रख सकते हैं और उसे घेर सकते हैं या उसे खो सकते हैं ...

try { doChuckAction(); } catch(ChuckNorrisException cne) { /*do something else*/ }


इस तरह के अपवाद के साथ यह System.exit(Integer.MIN_VALUE); का उपयोग करना अनिवार्य रूप से अनिवार्य होगा System.exit(Integer.MIN_VALUE); कन्स्ट्रक्टर से क्योंकि यदि आप इस तरह के अपवाद को फेंक देते हैं तो यह होगा;)


इस पर विचार करने के बाद, मैंने सफलतापूर्वक एक अपरिवर्तनीय अपवाद बनाया है। मैंने इसे JulesWinnfield नाम दिया, हालांकि, चक के बजाए, क्योंकि यह एक मशरूम-क्लाउड-बिछाने-मां-अपवाद है। इसके अलावा, यह आपके मन में बिल्कुल ठीक नहीं हो सकता है, लेकिन यह निश्चित रूप से पकड़ा नहीं जा सकता है। का निरीक्षण करें:

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! पकड़ा ना गया अपवाद।

आउटपुट:

चलाएँ:

वही से दुबारा कहें! मैं तुम्हें चुनौती देता हूं! मुझमे तुमसे दुगुनी हिम्मत है!

जावा परिणाम: 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)
    {

    }
}

एक ढेर ओवरफ्लो का कारण बनता है - फिर, अपवाद बेकार रहते हैं।


कोई भी कोड थ्रोबल पकड़ सकता है। तो नहीं, जो भी अपवाद आप बनाते हैं वह थ्रोबल के उप-वर्ग होने जा रहा है और पकड़े जाने के अधीन होगा।


जावा में अपवाद हैंडलिंग के साथ दो मौलिक समस्या यह है कि यह एक अपवाद के प्रकार का उपयोग करता है यह इंगित करने के लिए कि क्या कार्रवाई इसके आधार पर की जानी चाहिए, और जो कुछ भी अपवाद के आधार पर कार्रवाई करता है (यानी "पकड़" इसे हल करने के लिए माना जाता है) अंतर्निहित स्थिति। यह एक माध्यम होना उपयोगी होगा जिसके द्वारा एक अपवाद ऑब्जेक्ट तय कर सकता है कि कौन से हैंडलर को निष्पादित करना चाहिए, और क्या अब तक जिन हैंडलर ने निष्पादित किया है, उन्होंने मौजूदा विधि के लिए अपनी निकास स्थितियों को पूरा करने के लिए पर्याप्त चीजों को साफ कर दिया है। हालांकि इसका उपयोग "अचूक" अपवाद बनाने के लिए किया जा सकता है, दो बड़े उपयोग (1) अपवाद बनाते हैं जिन्हें केवल कोड द्वारा पकड़ा जाता है, जो वास्तव में जानता है कि उनके साथ कैसे निपटना है, और (2) अनुमति दें finally ब्लॉक में होने वाले अपवादों के समझदार हैंडलिंग के लिए (यदि एक बार FooException दौरान finally ब्लॉक के दौरान एक BarException , दोनों अपवादों को कॉल स्टैक को प्रसारित करना चाहिए; दोनों को पकड़ने योग्य होना चाहिए, लेकिन दोनों को तब तक जारी रखना चाहिए जब तक दोनों पकड़े नहीं जाते) । दुर्भाग्यवश, मुझे नहीं लगता कि मौजूदा अपवाद-हैंडलिंग कोड को चीजों को तोड़ने के बिना इस तरह से काम करने का कोई तरीका होगा।


नहीं। जावा में सभी अपवादों को java.lang.Throwable subclass करना चाहिए। java.lang.Throwable , और हालांकि यह अच्छा अभ्यास नहीं हो सकता है, आप हर तरह के अपवाद को पकड़ सकते हैं जैसे:

try {
    //Stuff
} catch ( Throwable T ){
    //Doesn't matter what it was, I caught it.
}

अधिक जानकारी के लिए java.lang.Throwable दस्तावेज देखें।

यदि आप चेक अपवादों से बचने की कोशिश कर रहे हैं (जिन्हें स्पष्ट रूप से संभाला जाना चाहिए) तो आप त्रुटि, या रनटाइम अपवाद को उपclass करना चाहेंगे।


मेरा जवाब @ jtahlborn के विचार पर आधारित है, लेकिन यह एक पूरी तरह से काम कर रहा Java प्रोग्राम है, जिसे एक JAR फ़ाइल में पैक किया जा सकता है और वेब एप्लिकेशन के हिस्से के रूप में भी आपके पसंदीदा एप्लिकेशन सर्वर पर तैनात किया जा सकता है।

सबसे पहले, ChuckNorrisException क्लास को परिभाषित ChuckNorrisException ताकि यह शुरुआत से JVM को क्रैश न करे (चक वास्तव में 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 करने के लिए 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

कोई आश्चर्य नहीं - यह सब के बाद एक गोलाकार किक है :)


वर्तमान धागे पर एक बेजोड़ अपवाद अनुकरण करना आसानी से संभव है। यह एक बेजोड़ अपवाद के नियमित व्यवहार को ट्रिगर करेगा, और इस प्रकार नौकरी को अर्थात् पूरा किया जाता है। हालांकि, यह वर्तमान धागे के निष्पादन को जरूरी नहीं रोकता है, क्योंकि वास्तव में कोई अपवाद नहीं डाला जाता है।

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 को पकड़ने (और छोड़ने) के ढांचे से बुलाया जाता है।


विषय पर एक संस्करण आश्चर्यजनक तथ्य है कि आप जावा कोड से अविकसित चेक अपवाद फेंक सकते हैं। चूंकि इसे विधियों के हस्ताक्षर में घोषित नहीं किया गया है, इसलिए संकलक आपको अपवाद को पकड़ने नहीं देगा, हालांकि आप इसे 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 एक चेक अपवाद है, तो एक अपवाद को पकड़ने के बारे में जो फेंक नहीं है।


finalize में System.exit (1) पर कॉल करें, और केवल अन्य सभी विधियों से अपवाद की एक प्रति फेंक दें, ताकि प्रोग्राम बाहर निकल जाए।


public class ChuckNorrisException extends Exception {
    public ChuckNorrisException() {
        System.exit(1);
    }
}

( ChuckNorrisException , तकनीकी रूप से यह अपवाद वास्तव में कभी नहीं फेंक दिया जाता है, लेकिन उचित ChuckNorrisException अपवाद को फेंक नहीं दिया जा सकता है - यह आपको पहले फेंकता है।)







aop