600

架空のキャッチ不能になるコードのスニペットをJavajava.lang.ChuckNorrisExceptionで構築することは可能ですか?

頭に浮かんだ考えは、たとえばインターセプターやアスペクト指向プログラミングを使用しています。

4

17 に答える 17

318

私はこれを試したことがないので、 JVMがこのようなものを制限するかどうかはわかりませんが、スローするコードをコンパイルできますが、実行時にThrowableを拡張しないChuckNorrisExceptionクラス定義を提供しChuckNorrisExceptionます。

アップデート:

動作しません。ベリファイアエラーが生成されます。

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.

「extendsRuntimeException」をコメントアウトし、再コンパイル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"
于 2012-12-14T17:27:27.823 に答える
121

これを熟考した後、私はキャッチできない例外を正常に作成しました。JulesWinnfieldただし、これは1つのキノコ雲、産卵、母の例外であるため、チャックではなく名前を付けることにしました。さらに、それはあなたが考えていたものと正確に一致しないかもしれませんが、それは確かに捕らえることができません。観察:

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

出来上がり!捕捉されなかった例外。

出力:

走る:

もう一度「何」と言ってください!出来ることならどうぞ!私はあなたを二重に敢えてします!

Javaの結果:8

BUILD SUCCESSFUL(合計時間: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)
    {
        
    }
}

スタックオーバーフローを引き起こします-繰り返しますが、例外はキャッチされないままです。

于 2012-12-15T12:16:53.727 に答える
85

そのような例外を除いて、コンストラクターからaを使用することは明らかに必須System.exit(Integer.MIN_VALUE);です。これは、そのような例外をスローした場合に発生するためです;)

于 2012-12-14T17:15:14.427 に答える
46

どのコードでもThrowableをキャッチできます。したがって、作成する例外はすべてThrowableのサブクラスになり、キャッチされる可能性があります。

于 2012-12-14T17:09:10.307 に答える
35
public class ChuckNorrisException extends Exception {
    public ChuckNorrisException() {
        System.exit(1);
    }
}

(確かに、技術的には、この例外が実際にスローされることはありませんが、適切なChuckNorrisExceptionものをスローすることはできません。最初にスローされます。)

于 2012-12-15T19:01:16.470 に答える
28

スローする例外はすべてThrowableを拡張する必要があるため、常にキャッチできます。だから答えはノーです。

処理を困難にしたい場合は、メソッドをオーバーライドしてgetCause(), getMessage()、別のをスローすることができます。getStackTrace()toString()java.lang.ChuckNorrisException

于 2012-12-14T17:17:13.820 に答える
25

私の答えは@jtahlbornのアイデアに基づいていますが、これは完全に機能するJavaプログラムであり、 JARファイルにパッケージ化でき、 Webアプリケーションの一部としてお気に入りのアプリケーションサーバーにデプロイすることもできます。

まずChuckNorrisException、最初からJVMがクラッシュしないようにクラスを定義しましょう(チャックはJVMのクラッシュが大好きです:)

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

当然のことながら、それは結局のところ回し蹴りです:)

于 2012-12-18T22:56:28.737 に答える
15

コンストラクターでは、繰り返し呼び出すスレッドを開始できますoriginalThread.stop (ChuckNorisException.this)

スレッドは例外を繰り返しキャッチできますが、終了するまで例外をスローし続けます。

于 2012-12-14T20:55:14.863 に答える
13

いいえ。Javaのすべての例外はサブクラス化する必要java.lang.Throwableがあります。これは良い習慣ではないかもしれませんが、次のようにあらゆる種類の例外をキャッチできます。

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

詳細については、java.lang.Throwableのドキュメントを参照してください。

チェックされた例外(明示的に処理する必要がある例外)を回避しようとしている場合は、ErrorまたはRuntimeExceptionをサブクラス化する必要があります。

于 2012-12-14T17:09:38.367 に答える
9

Javaは検証なしで実行する必要があるため、実際には受け入れられた答えはあまり良くありません。つまり、コードは通常の状況では機能しません。

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)
于 2014-04-19T10:42:44.850 に答える
8

テーマのバリエーションは、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;
  }
}

ChuckNorrisExceptionthrow SneakyThrow.sneak(new ChuckNorrisException());をスローしますが、コンパイラは次のように文句を言います。

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

ChuckNorrisExceptionがチェックされた例外である場合にスローされない例外をキャッチすることについて。

于 2012-12-22T08:32:20.403 に答える
6

ChuckNorrisExceptionJavaの唯一のsはとである必要がOutOfMemoryErrorありStackOverflowErrorます。

実際には、例外がスローされた場合にaが実行されるという意味でそれらを「キャッチ」できますがcatch(OutOfMemoryError ex)、そのブロックは自動的に例外を呼び出し元に再スローします。

私はそれがうまくいくとは思いませんpublic class ChuckNorrisError extends Errorが、あなたはそれを試してみることができます。拡張に関するドキュメントが見つかりませんでしたError

于 2012-12-15T12:01:31.087 に答える
6

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。なんで?スローできないオブジェクトは、スローできないものをキャッチできないため、定義上、キャッチできません。

于 2012-12-18T08:19:17.127 に答える
3

ChuckNorrisを内部または非公開にして、カプセル化するか、膨らませることができます...

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

于 2012-12-15T04:39:23.933 に答える
3

Javaでの例外処理に関する2つの基本的な問題は、例外のタイプを使用して、それに基づいてアクションを実行する必要があるかどうかを示すことと、例外に基づいてアクションを実行する(つまり、それを「キャッチ」する)ものはすべて解決すると推定されることです。根本的な状態。例外オブジェクトがどのハンドラーを実行するかを決定できる手段があれば便利です。また、これまでに実行したハンドラーが、現在のメソッドが終了条件を満たすのに十分なクリーンアップを行っているかどうかを判断できます。これは「キャッチできない」例外を作成するために使用できますが、2つの大きな使用法は、(1)実際にそれらを処理する方法を知っているコードによってキャッチされた場合にのみ処理されると見なされる例外を作成することです。finallyFooExceptionの巻き戻し中のfinallyブロック中にBarException、両方の例外がコールスタックに伝播する必要があります。両方ともキャッチ可能である必要がありますが、両方がキャッチされるまで巻き戻しを続ける必要があります)。残念ながら、既存の例外処理コードを壊すことなくそのように機能させる方法はないと思います。

于 2012-12-15T23:53:16.143 に答える
1

現在のスレッドでキャッチされていない例外をシミュレートすることは簡単に可能です。これにより、キャッチされない例外の通常の動作がトリガーされ、セマンティックにジョブが実行されます。ただし、実際には例外がスローされないため、必ずしも現在のスレッドの実行が停止するわけではありません。

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

于 2016-01-09T00:37:23.377 に答える
0

でSystem.exit(1)を呼び出しfinalize、他のすべてのメソッドから例外のコピーをスローするだけで、プログラムが終了します。

于 2014-04-18T01:23:38.533 に答える