4

すべてのエラーを大きな包括的な catch ブロックでキャッチするスレッドがあります。これは、予想されるエラーだけでなく、アプリケーションのエラーを報告できるようにするためです。私の Runnable は次のようになります。

public final void run()
{
    try
    {
        System.out.println("Do things"); /* [1] */

        doUnsafeThings();
    }
    catch (Throwable t)
    {
        System.out.println("Catch"); /* [2] */

        recover();
    }
    finally
    {
        System.out.println("Finally"); /* [3] */
    }
}

NPE が Throwable catch ブロックによってキャッチされることを期待します。代わりに、[2] の出力は印刷されず、[3] も印刷されません。[1] の出力が印刷されます。

コンソールで得られるのは次のとおりです。

Uncaught exception java/lang/NullPointerException.

ここで何が起こっているのですか?

法廷記録のために、私は J2ME を使用しており、これは Sun の WTK v2.5.2 エミュレーターで実行されています。

私はそれを JVM 実装の怪しさのせいだと言いたくなるのですが、何かが足りないと感じずにはいられません。

誤解を避けるために明確にするために(サンプルコードは私の製品コードから明らかに変更されているため)

  • run メソッドの try/catch/finally ブロックの外側には何もありません。
  • これらの各ブロックの先頭に System.out.println があります。これらのコンソール ステートメントに続くものは重要ではありません。
4

9 に答える 9

6

答えは、私がばかだということがわかりました。何がうまくいかなかったのかを説明しますが、それを「それらのバグの 1 つ」と呼びましょう。

ランナブルを実行したスレッドがカスタム スレッド クラスであることを一時的に忘れていました (Nokia のバグを回避するため)。run()メソッドの呼び出しの間に繰り返し呼び出されましたcanWait()

canWait メソッドが失敗の原因であり、run はまったく失敗していませんでした。それに加えて、私はコンソール盲目であり、質問の一連のイベントを完全に誤って誤って引用しました。

于 2009-04-22T13:16:42.530 に答える
5

試行錯誤が必要なようです。私が提案してもいいですか:

try {
    doEvilStuff();
} catch (NullPointerException ex) { 
    System.out.println("NPE encountered in body"); 
} catch (Throwable ex) {
    System.out.println("Regular Throwable: " + ex.getMessage());
} finally {
    etc...
}

NullPointerExceptionの明示的なキャッチを設定することにより、例外がtryブロック内からのものかcatch/finallyブロック内からのものかが明らかになるはずです。

于 2009-04-22T11:54:47.767 に答える
4

わかりました、これは大げさな推測です...しかし、それは物事を説明するでしょう.

明らかに、あなたのコードは実際にはそうではありません.catch(またはfinally)ブロックは、何かをログに記録する前に何かを行っているか tryブロックとは異なるロガーを使用していると思います。いずれにせよ、catch または finally ブロックのいずれかが例外をスローしていると思われます。

スタックトレースがあるとは思いません...

編集:オーケー、それがただの場合、それSystem.out.printlnは議論の中で何かが爆発する可能性がありますか? 例えば:

catch (Throwable t) {
    // Will go bang if t.getCause() returns null
    System.out.println(t.getCause().getMessage());
}

それが単純だとしたらSystem.out.println("Constant")、それは非常に奇妙です。

(たとえば、try ブロック内のログ行から) try ブロックが実際にどこまで進んでいるか知っていますか?

于 2009-04-22T11:46:59.703 に答える
2

あなたが使用していると述べたようにRunnable、これはおそらく複数のスレッドも使用していることを意味しますか? doUnsafeThings()メソッドが内部的に別のスレッドを再び生成し、それが例外を生成する場合、catch ブロックが存在するスレッドでそれを取得できない可能性があります。http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Thread.UncaughtExceptionHandler.htmlを参照してください。

于 2009-04-22T13:11:04.527 に答える
2

あなたのコードを見ると、recover() が例外をスローしているように見えるので、Jon からのアドバイスに従うのは素晴らしいことです。

スタック トレースを提供していただければ、より適切なサポートが得られる可能性があります。

例外をキャッチしようとすると、次のようにします。

try {
  doSomethingBad();
} catch(Exception e) {
   try {
      LogException(...);
   } catch(Exception e) {}       
} finally {
}

例外を入れ子にするのは好きではありませんが、catch ブロックが例外をスローするのは好きではありません。

于 2009-04-22T12:06:43.543 に答える
1

一般に、NullPointerException をキャッチすることはお勧めできません。

プログラマーは通常、次の 3 つの状況で NullPointerException をキャッチします。

The program contains a null pointer dereference. Catching the resulting exception was easier than fixing the underlying problem.
The program explicitly throws a NullPointerException to signal an error condition.
The code is part of a test harness that supplies unexpected input to the classes under test. 

これら 3 つの状況のうち、最後の状況のみが許容されます。このリンクをたどる:

NullPointerException をキャッチ

于 2012-11-17T05:30:21.610 に答える
0
  • コード内の正しい場所を見ていますか? つまり、スタック トレースで保護している doUnsafeThings() ブロックですか?

  • ビルド方法に問題があり、古いバージョンのコードをデバッグしている可能性がありますか?

于 2009-04-22T12:10:51.317 に答える
0

doUnsafeThings(); にログを追加するだけです。そのメソッドが期待どおりに機能しているかどうかを確認します (たとえば、try catch を最後に配置して、何かをログに記録します)。

于 2009-04-22T13:01:35.097 に答える
0

スレッドが他のコードによって強制終了されている可能性はありますか? 一般に、System.exit() などによってスレッドが異常終了しない限り、finally ブロックは常に実行されます。

于 2009-04-22T11:40:48.720 に答える