仮説をキャッチできないようにするJavaのコードのスニペットを構築することは可能java.lang.ChuckNorrisException
ですか?
頭に浮かんだ考えは、たとえばインターセプターやアスペクト指向プログラミングを使用しています。
finalize()
どうですか?
仮説をキャッチできないようにするJavaのコードのスニペットを構築することは可能java.lang.ChuckNorrisException
ですか?
頭に浮かんだ考えは、たとえばインターセプターやアスペクト指向プログラミングを使用しています。
finalize()
どうですか?
回答:
場合、私は知らないので、私は、これを試していないJVMがこのような何かを制限するだろうが、多分あなたはスローコードをコンパイルすることができChuckNorrisException
ますが、実行時のクラス定義に提供ChuckNorrisException
されたThrowableを拡張しませんが。
更新:
動作しません。検証エラーが生成されます。
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.
「extends RuntimeException」をコメントアウトして、再コンパイル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"
Object
では、ではなくをキャッチした場合はどうなるでしょThrowable
うか。(コンパイラーはそれを許可しませんが、ベリファイアをすでに無効にしているので、バイトコードをハックしてそれを行うことができます。)
これについて熟考した後、私はキャッチできない例外を作成しました。JulesWinnfield
ただし、キノコの雲の敷設、母の例外の1つであるため、Chuckではなくと名付けました。さらに、それはあなたが心に描いていたものとは正確には違うかもしれませんが、確実に捕まえることはできません。観察する:
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
成功したビルド(合計時間: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)
{
}
}
スタックオーバーフローを引き起こします-ここでも、例外は捕捉されません。
JulesWinfield
?システムは、スローされる前にきしむような停止になりませんか?
throw new Whatever()
は実際には2つの部分で構成されています。Whatever it = new Whatever(); throw it;
システムは2番目の部分に到達する前にシステムが停止します。
class cn extends exception{private cn(){}}
そのような例外があるとSystem.exit(Integer.MIN_VALUE);
、コンストラクタからのaを使用することが明らかに必須になります。これは、そのような例外をスローした場合に起こることだからです;)
while(true){}
代わりに使用できますSystem.exit()
。
System.exit()
。これにより、コンストラクターが別の例外(SecurityException)に変わり、キャッチできます。
どのコードでもThrowableをキャッチできます。したがって、作成した例外はすべてThrowableのサブクラスになり、キャッチされる可能性があります。
hang
、ChuckNorrisException:P
public class ChuckNorrisException extends Exception {
public ChuckNorrisException() {
System.exit(1);
}
}
(確かに、技術的にはこの例外は実際にはスローされChuckNorrisException
ませんが、適切なものはスローできません-最初にスローされます。)
スローする例外はすべてThrowableを拡張する必要があるため、常にキャッチできます。だから答えはノーです。
処理を困難にしたい場合getCause(), getMessage()
はgetStackTrace()
、メソッドをオーバーライドして、toString()
別のをスローすることができますjava.lang.ChuckNorrisException
。
catch(Throwable t)
それを変数に保存するだけだと思うので、私の提案は、ユーザーが例外に対処したいときに次のブロックにのみ適用されます
私の答えは@jtahlbornの考えに基づいていますが、これは完全に機能するJavaプログラムであり、JARファイルにパッケージ化して、Webアプリケーションの一部としてお気に入りのアプリケーションサーバーにデプロイすることもできます。
最初にChuckNorrisException
、最初からJVMをクラッシュさせないようにクラスを定義しましょう(チャックは本当にJVMをクラッシュさせるのが大好きです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
それを構築するためにクラスに行きます:
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
驚きではありません-それは結局のところ大振りのキックです:)
いいえ。Javaのすべての例外はをサブクラス化する必要java.lang.Throwable
があります。これは良い習慣ではないかもしれませんが、次のようにすべてのタイプの例外をキャッチできます。
try {
//Stuff
} catch ( Throwable T ){
//Doesn't matter what it was, I caught it.
}
詳細については、java.lang.Throwableのドキュメントを参照してください。
チェックされた例外(明示的に処理する必要があるもの)を回避しようとしている場合は、ErrorまたはRuntimeExceptionをサブクラス化する必要があります。
実際には、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)
テーマのバリアントは、宣言されていないチェック済み例外を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;
}
}
今throw SneakyThrow.sneak(new ChuckNorrisException());
はChuckNorrisExceptionをスローしますが、コンパイラは不平を言います
try {
throw SneakyThrow.sneak(new ChuckNorrisException());
} catch (ChuckNorrisException e) {
}
ChuckNorrisExceptionがチェック済み例外である場合にスローされない例外のキャッチについて。
ChuckNorrisException
Java の唯一のはとである必要がOutOfMemoryError
ありStackOverflowError
ます。
catch(OutOfMemoryError ex)
例外がスローされた場合にa が実行されるという意味で実際にそれらを「キャッチ」できますが、そのブロックは例外を呼び出し元に自動的に再スローします。
私はそれでうまくいくとは思いませんpublic class ChuckNorrisError extends Error
が、あなたはそれを試すことができます。拡張に関するドキュメントは見つかりませんでしたError
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
。どうして?スローできないオブジェクトは、スローすることができないものをキャッチすることができないため、定義によりキャッチできません。
java.lang.ChuckNorrisException
、例外は例外であるということは言うまでもなく、投げることはできない
あなたはChuckNorrisを内部またはプライベートに保ち、彼をカプセル化するか、彼を飲み込むことができます...
try { doChuckAction(); } catch(ChuckNorrisException cne) { /*do something else*/ }
Javaでの例外処理に関する2つの基本的な問題は、例外のタイプを使用して、それに基づいてアクションを実行する必要があるかどうかを示すことと、例外に基づいてアクションを実行するもの(つまり、それを「キャッチ」)が解決すると推定されることです。根本的な状態。例外オブジェクトがどのハンドラーを実行する必要があるかを決定する手段と、これまでに実行されたハンドラーが現在のメソッドがその終了条件を満たすのに十分なクリーンアップを行っているかどうかが役立つと便利です。これは「キャッチできない」例外を作成するために使用できますが、2つの大きな用途は(1)例外を作成することです。例外は、実際にそれらを処理する方法を知っているコードによってキャッチされた場合にのみ処理されると見なされます。finally
FooException
finally
の巻き戻し中のブロック中はBarException
、両方の例外が呼び出しスタックに伝達されます。どちらもキャッチ可能でなければなりませんが、両方がキャッチされるまで巻き戻しを続ける必要があります)。残念ながら、既存の例外処理コードを壊すことなくそのように機能させる方法はないと思います。
finally
ブロックが前の例外からクリーンアップしているときに例外が発生した場合、どちらか一方の例外が、もう一方の例外がない場合、コードが処理して続行すると予期されるものである可能性が高いです。しかし、一方を処理して他方を無視するのは悪いことです。ただし、両方のハンドラが処理する複合例外を生成するメカニズムはありません。
Foo
が、Foo
それ自体をスローしたか、故意にそれをスローしたふりをしたい例外とFoo
、それが発生したときに発生すると予期していなかった例外を区別できる手段があるはずだということです。他のメソッドを呼び出す。「チェック」例外の概念は「約」であるべきです。
現在のスレッドでキャッチされない例外をシミュレートすることは簡単に可能です。これにより、キャッチされない例外の通常の動作がトリガーされ、意味的にジョブが実行されます。ただし、実際には例外がスローされないため、必ずしも現在のスレッドの実行を停止するわけではありません。
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
処理が必要であるが、メソッドがanyをキャッチ(および破棄)するフレームワークから呼び出される場合などThrowable
です。