Uncatchable ChuckNorrisException
Asked Answered
H

17

605

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

Thoughts that came to mind are using for example interceptors or aspect-oriented programming.

Heatstroke answered 14/12, 2012 at 17:5 Comment(12)
An interesting question indeed... I suspect the question is really "can you throw a non-exception? (Something that doesn't derive from Throwable?)" JNI ThrowNew perhaps?Hanhhank
What can you throw in Java?Housemaster
using the suggestion from the link @jschoen provided (disable the byte code verifier) you can throw something which doesn't extend Throwable! described in my answer below.Brachial
This excerpt from aioobe's answer sums up the question @jschoen linked quite well: "I.e., your question can be interpreted as 'If a JVM deviates from the specification, can it do weird stuff such as throwing primitivs' and the answer is of course, yes."Encumbrancer
I dont know if its works, but you could try to overide the throwable contructor, throwing another error...Lorrimor
@Max - Can you elaborate on practical uses for this?Griseofulvin
how about an exception that rethrow itself on the finalize()?Oakie
@LieRyan That would rather be a WormTongueException. Very sneaky, and when you except it the least, it kills you.Kaminsky
@LieRyan - throwing an exception from the finalize() method doesn't do anything, it's ignored. and finalize() is called by the gc, so it doesn't stop the original throw from being caught.Brachial
I know this one is marked as unanswered. Anyway, I think I found a better solution doing what you asked for. Would you please accept and upvote my answer if it seems appropriate? Thanks.Microfiche
Completely wrong approach. Chuck Norris isn't the Throwable, but the catcher! He even succeeds with null. ;-)Larentia
By definition, you can't throw ChuckNorrisException. At most ChuckNorrisException's constructor can throw you and your computer out of your window with a roundhouse kickIsidor
B
320

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"
Brachial answered 14/12, 2012 at 17:27 Comment(9)
OK, so what if you catch Object instead of Throwable, then? (The compiler won't allow it, but since we've already disabled the verifier, maybe one could hack the bytecode to do it.)Organ
@IlmariKaronen - don't know. i didn't actually have to hack byte code for my test, just recompile a class.Brachial
According to What can you throw in Java you can still catch things that don't extend throwable, but throwing and catching them is undefined behavior.Gavra
@jex, So you can catch them or catching them is undefined behavior? Both cannot be true.Citadel
@Citadel They can be true together. You might be able to catch them using your version of the Java environment on your specific version of your operating system on your processor type. But if it's not specified in the standard whether it CAN be caught, it's called undefined behavior, because other implementations of Java might choose to make it non-catchable.Pardner
Hmmph. I was hoping that for 176 upvotes, you'd written some JNI code that monkey-patches the entire call stack to rethrow your exception (called by the ctor, of course).Chinkapin
@Chinkapin - eagerly awaiting your answer... :)Brachial
When doing all of this, it's also a great idea to stand on one leg, pat your head and rub your tummy while whistling dixie...;) ;)Technocracy
"following from Home .." :)Caffeine
D
122

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.

Digester answered 15/12, 2012 at 12:16 Comment(15)
+1 for using Stack Overflow in your answer. Just kidding, really good answer.Dowland
I'll just take your word for it on the coding front, but +1 for the creative naming conventions and example text!Leelah
A proper "uncatchable exception" would ensure that all enclosing finally blocks would execute without any intervening catches. Killing the system doesn't throw an exception--it just kills the system.Tannate
@Tannate you are right, and I'm going to keep fiddling with these when I have time. I'm just showing that it is possible to throw an exception which couldn't be caught. Aside: the first example would also work for a situation in which a finally block would fail to execute.Digester
How do you "throw" the JulesWinfield? Won't the system come to a screeching halt before it's thrown?Tannate
@Tannate No, it throws just fine, as evidenced by the System.out.print(Say... statement. It's during the throw that everything blows up and the program exits.Digester
@mikeTheLiar: The system exits during the constructor, does it not? The statement throw new Whatever() is really two parts: Whatever it = new Whatever(); throw it;, and the system dies before it reaches the second part.Tannate
@Tannate Hmm. I suspect you might be right. This will require further investigation. Once I have sobered up.Digester
actually, you can prevent System.exit() from working by installing a security manager which disallows it. that would turn the constructor into a different exception (SecurityException), which could be caught.Brachial
@Tannate you're definitely right. I'm going to try to come up with something better and update my answer when I have a second.Digester
Actually, you can catch a stackOverflowError.Baumbaugh
@JanDvorak, yes, but you can't catch a Jules or Vincent. A technicality, to be sure, but but technically correct is the best kind of correct. No seriously though, this needs work, but I need free time which is a commodity at this point. I do plan on polishing this, I wrote this answer in about 5 minutes.Digester
@mikeTheLiar you actually can catch Jules or Vincent quite easily... if you manage to throw it. It's easy to create an exception that you can't throw: class cn extends exception{private cn(){}}Baumbaugh
To clarify, it can't be caught because creating the exception causes the program to exit?Malloch
@AaronFranke yeah, the other comments elucidate this. I've been meaning to update this answer for a while now but never got around to it. In a nutshell, you can't catch it because you can't throw it and you can't throw it because you can't construct it.Digester
F
85

With such an exception it would obviously be mandatory to use a System.exit(Integer.MIN_VALUE); from the constructor because this is what would happen if you threw such an exception ;)

Fulks answered 14/12, 2012 at 17:15 Comment(10)
+1; IMO this is the only possible solution. An uncatchable exception is should terminate the program...Heidy
No, it would not be what happens when you throw such an exception. An uncaught exception will terminate a single thread, it will not exit the jvm, in some contexts System.exit itself will even cause a SecurityException - not every piece of code is allowed to shutdown a program.Horwitz
You can use while(true){} instead of System.exit().Lacerta
actually, you can prevent System.exit() from working by installing a security manager which disallows it. that would turn the constructor into a different exception (SecurityException), which could be caught.Brachial
@Banthar while(true); is a horrible thing to do because, while it essentially prevents execution of the current thread it still requires work (though not much of it), because the thread is still alive. This wastes a lot of processing power on context switches in the CPU, and will result in a significant performance drop if used multiple times.Ketene
@Ketene I assume it doesn't matter when you are trying to throw uncatchable exceptions. Both should never be done in serious code.Lacerta
True that neither should really be done, but it doesn't mean you should recommend it as an action.Ketene
Umm, technically you never threw an exception. You haven't even constructed the object to throw yet!Toomay
@ThomasEding I was just waiting for that comment :-)Fulks
It's still not great practice, as you're still paying for the context switch, just not as often. It's best to just kill the thread outright.Ketene
S
46

Any code can catch Throwable. So no, whatever exception you create is going to be a subclass of Throwable and will be subject to being caught.

Shon answered 14/12, 2012 at 17:9 Comment(1)
Throwable would hang itself in an attempt to catch ChuckNorrisException :PGalliwasp
D
35
public class ChuckNorrisException extends Exception {
    public ChuckNorrisException() {
        System.exit(1);
    }
}

(Granted, technically this exception is never actually thrown, but a proper ChuckNorrisException can't be thrown -- it throws you first.)

Diphenylhydantoin answered 15/12, 2012 at 19:1 Comment(2)
A colleague of mine had suggested sticking 'for(;;){}' as he felt a 'System.exit(1)' call could throw a Security Exception. I'm voting this one up for creativity!Hilly
I agree with the end of your answer. Never mess with ChuckNorris, Exception or not.Tangelatangelo
N
28

Any exception you throw has to extend Throwable, so it can be always caught. So answer is no.

If you want to make it difficult to handle, you can override methods getCause(), getMessage(), getStackTrace(), toString() to throw another java.lang.ChuckNorrisException.

Nightcap answered 14/12, 2012 at 17:17 Comment(2)
Hmm, catch(Throwable t) call any methods or otherwise mutate the object? It may be possible to cause a catch clause to further throw an exception therefor making it impossible.Verditer
I think catch(Throwable t) only stores it into variable so my suggestions only apply in the next block when user want to cope with the exceptionNightcap
Z
25

My answer is based on @jtahlborn's idea, but it's a fully working Java program, that can be packaged into a JAR file and even deployed to your favorite application server as a part of a web application.

First of all, let's define ChuckNorrisException class so that it doesn't crash JVM from the beginning (Chuck really loves crashing 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);
    }
}

Now goes Expendables class to construct it:

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

And finally the Main class to kick some butt:

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

Compile and run it with following command:

java -Xverify:none -cp .:<path_to_javassist-3.9.0.GA.jar> chuck.Main

You will get following output:

before
finally

No surprise - it's a roundhouse kick after all :)

Zettazeugma answered 18/12, 2012 at 22:56 Comment(4)
very nice! haven't done much with class definition manipulation myself. do you still need the "verify:none" on the commandline?Brachial
@Brachial Yes, attempt to throw an object not being descendant of Throwable fails without "verify:none".Zettazeugma
oh, i got the impression this somehow got around that constraint. so how is this different from my answer?Brachial
The main difference is that it's working java code without compile-time hackingZettazeugma
F
15

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.

Firebird answered 14/12, 2012 at 20:55 Comment(0)
G
13

No. All exceptions in Java must subclass java.lang.Throwable, and although it may not be good practice, you can catch every type of exception like so:

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

See the java.lang.Throwable documentation for more information.

If you're trying to avoid checked exceptions (ones that must be explicitly handled) then you will want to subclass Error, or RuntimeException.

Gavra answered 14/12, 2012 at 17:9 Comment(0)
M
9

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)
Microfiche answered 19/4, 2014 at 10:42 Comment(0)
T
8

A variant on the theme is the surprising fact that you can throw undeclared checked exceptions from Java code. Since it is not declared in the methods signature, the compiler won't let you catch the exception itself, though you can catch it as java.lang.Exception.

Here's a helper class that lets you throw anything, declared or not:

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

Now throw SneakyThrow.sneak(new ChuckNorrisException()); does throw a ChuckNorrisException, but the compiler complains in

try {
  throw SneakyThrow.sneak(new ChuckNorrisException());
} catch (ChuckNorrisException e) {
}

about catching an exception that is not thrown if ChuckNorrisException is a checked exception.

Tricyclic answered 22/12, 2012 at 8:32 Comment(0)
G
6

The only ChuckNorrisExceptions in Java should be OutOfMemoryError and StackOverflowError.

You can actually "catch" them in the means that a catch(OutOfMemoryError ex) will execute in case the exception is thrown, but that block will automatically rethrow the exception to the caller.

I don't think that public class ChuckNorrisError extends Error does the trick but you could give it a try. I found no documentation about extending Error

Gambill answered 15/12, 2012 at 12:1 Comment(6)
Error still extends Throwable so no way to prevent catching it. That is by design of the Java language.Chinchilla
@JasonM1 I don't think the OP asked for an actually "uncatchable" exception, and I meant that Error propagates even if you catch it. So, any Throwable is catchable but these two will eventually propagate no matter what you doIsidor
To be tricky ChuckNorrisException could extend Throwable directly then it would be neither Exception nor Error!Chinchilla
But then catch(Throwable) catches it and prevents rethrowingIsidor
Error does not propagate even if you catch it, i'm not sure where you got that idea.Brachial
I think you are well confused about Erros, they are normal exceptions like everything that extends Throwable or even Throwable, itself.Mehetabel
T
6

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

Yes, and here's the answer: Design your java.lang.ChuckNorrisException such that it is not an instance of java.lang.Throwable. Why? An unthrowable object is uncatchable by definition because you can never catch something that can never be thrown.

Toomay answered 18/12, 2012 at 8:19 Comment(3)
But then it is not an exception.Husted
@dolbi: I can find no place in the OP's question that states java.lang.ChuckNorrisException must be an exception, let alone throwableToomay
I guess its not stated, but it is implied. You are a mathematician :-) , aren't you?Husted
T
3

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

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

Thickness answered 15/12, 2012 at 4:39 Comment(3)
I don't believe the idea was to catch it. I think the idea is to prevent it from being caught.Bartlet
Correct me if I am wrong but if you make it internal you cannot get to it without reflection.Thickness
yes, but as long as you can catch Exception or Throwable the visibility of the actual type is irrelevant.Sharlasharleen
T
3

Two fundamental problems with exception handling in Java are that it uses the type of an exception to indicate whether action should be taken based upon it, and that anything which takes action based upon an exception (i.e. "catch"es it) is presumed to resolve the underlying condition. It would be useful to have a means by which an exception object could decide which handlers should execute, and whether the handlers that have executed so far have cleaned things up enough for the present method to satisfy its exit conditions. While this could be used to make "uncatchable" exceptions, two bigger uses would be to (1) make exceptions which will only be considered handled when they're caught by code that actually knows how to deal with them, and (2) allow for sensible handling of exceptions which occur in a finally block (if a FooException during a finally block during the unwinding of a BarException, both exceptions should propagate up the call stack; both should be catchable, but unwinding should continue until both have been caught). Unfortunately, I don't think there would be any way to make existing exception-handling code work that way without breaking things.

Tannate answered 15/12, 2012 at 23:53 Comment(6)
an interesting idea, but i don't think the low-level code would know what a particular exception "means" to the caller, so i don't think it would ever make sense for the thrower to decide which handlers should execute.Brachial
@jtahlborn: Right now, the thrower decides what exception handlers should execute via the choice of exception type. This makes it all but impossible to handle some scenarios cleanly. Among other things: (1) if an exception occurs while a finally block is cleaning up from an earlier exception, it's quite possible that either exception, in the absence of the other, may be something which code would be expect to handle and continue on, but that handling one and ignoring the other would be bad. There's no mechanism, though, to produce a composite exception that both handlers would process.Tannate
@jtahlborn: Also, it makes it makes it very difficult to allow exceptions that occur within callbacks to be handled by the outer application layer. If the callback's exception is wrapped in another exception type, the type of callback exception cannot be used in the outer layer in deciding whether to catch it; if it isn't wrapped, an "accidental" mid-layer exception may be mistaken for one that occurs in the callback. If a wrapped exception object were told when it was passed up to the outer application layer, it could then start answering to the types of the wrapped exceptions.Tannate
i wasn't arguing your other points, just the statement about the exception object deciding on which handlers will execute. to some extent exception types do that already, but it sounds like you wanted something more dynamic, which i was disagreeing with. i think your major argument (which you are kind of coming at sideways) is to capture as much information as you can at the bottom and let the upper layers see and work with all of that information. on this general point i agree with you, however the devil is in the details/implementation.Brachial
@jtahlborn: My intention was not to have the virtual methods implement anything particularly "dynamic", but essentially say "Is there a condition of the indicated type which should be acted upon". One thing I forgot to mention, though, is that there should be a means via which code which calls Foo can distinguish between an exception which Foo either threw itself or deliberately wants to pretend it threw itself, from one which Foo was not expecting to occur when it was calling some other method. That's what the notion of "checked" exceptions should be "about".Tannate
@jtahlborn: Rather than having checked-ness be a characteristic of an exception type, it should be a characteristic of catch and throw sites. If a call to Foo is wrapped in a try...catch checked BozException, the catch should only grab a BozException which Foo either threw or was expecting to "pass through". It should not catch a BozException which occurred (contrary to Foo's expectation) in a method Foo called.Tannate
G
1

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.

Grantinaid answered 9/1, 2016 at 0:37 Comment(0)
C
0

Call System.exit(1) in the finalize, and just throw a copy of the exception from all the other methods, so that the program will exit.

Chromatophore answered 18/4, 2014 at 1:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.