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
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
.
You can keep ChuckNorris internal or private and encapsulate him or swollow him...
try { doChuckAction(); } catch(ChuckNorrisException cne) { /*do something else*/ }
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"
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.
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.
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)