Uncatchable ChuckNorrisException

前端 未结 17 2003
时光取名叫无心
时光取名叫无心 2020-12-02 03:34

Is it possible to construct a snippet of code in Java that would make a hypothetical java.lang.ChuckNorrisException uncatchable?

Thoughts that came to m

相关标签:
17条回答
  • 2020-12-02 03:57

    It is easily possible to simulate a uncaught exception on the current thread. This will trigger the regular behavior of an uncaught exception, and thus gets the job done semantically. It will, however, not necessarily stop the current thread's execution, as no exception is actually thrown.

    Throwable exception = /* ... */;
    Thread currentThread = Thread.currentThread();
    Thread.UncaughtExceptionHandler uncaughtExceptionHandler =
        currentThread.getUncaughtExceptionHandler();
    uncaughtExceptionHandler.uncaughtException(currentThread, exception);
    // May be reachable, depending on the uncaught exception handler.
    

    This is actually useful in (very rare) situations, for example when proper Error handling is required, but the method is invoked from a framework catching (and discarding) any Throwable.

    0 讨论(0)
  • 2020-12-02 03:58

    You can keep ChuckNorris internal or private and encapsulate him or swollow him...

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

    0 讨论(0)
  • 2020-12-02 03:59

    I haven't tried this, so I don't know if the JVM would restrict something like this, but maybe you could compile code which throws ChuckNorrisException, but at runtime provide a class definition of ChuckNorrisException which does not extend Throwable.

    UPDATE:

    It doesn't work. It generates a verifier error:

    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.
    

    UPDATE 2:

    Actually, you can get this to work if you disable the byte code verifier! (-Xverify:none)

    UPDATE 3:

    For those following from home, here is the full script:

    Create the following classes:

    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.");
            }
        }
    }
    

    Compile classes:

    javac -cp . TestVillain.java ChuckNorrisException.java
    

    Run:

    java -cp . TestVillain
    Gotcha!
    The end.
    

    Comment out "extends RuntimeException" and recompile ChuckNorrisException.java only :

    javac -cp . ChuckNorrisException.java
    

    Run:

    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.
    

    Run without verification:

    java -Xverify:none -cp . TestVillain
    The end.
    Exception in thread "main"
    
    0 讨论(0)
  • 2020-12-02 03:59

    After having pondered this, I have successfully created an uncatchable exception. I chose to name it JulesWinnfield, however, rather than Chuck, because it is one mushroom-cloud-laying-mother-exception. Furthermore, it might not be exactly what you had in mind, but it certainly can't be caught. Observe:

    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");
        }
    }
    

    Et voila! Uncaught exception.

    Output:

    run:

    Say 'What' again! I dare you! I double dare you!

    Java Result: 8

    BUILD SUCCESSFUL (total time: 0 seconds)

    When I have a little more time, I'll see if I can't come up with something else, as well.

    Also, check this out:

    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)
        {
            
        }
    }
    

    Causes a stack overflow - again, exceptions remain uncaught.

    0 讨论(0)
  • 2020-12-02 04:01

    In the constructor you could start a thread which repeatedly calls originalThread.stop (ChuckNorisException.this)

    The thread could catch the exception repeatedly but would keep throwing it until it dies.

    0 讨论(0)
  • 2020-12-02 04:05

    Actually the accepted answer is not so nice because Java needs to be run without verification, i.e. the code would not work under normal circumstances.

    AspectJ to the rescue for the real solution!

    Exception class:

    package de.scrum_master.app;
    
    public class ChuckNorrisException extends RuntimeException {
        public ChuckNorrisException(String message) {
            super(message);
        }
    }
    

    Aspect:

    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;
        }
    }
    

    Sample application:

    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!");
        }
    }
    

    Output:

    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)
    
    0 讨论(0)
提交回复
热议问题