- PR -

catch を書かなくても例外発生時にエラーメッセージを出したい

投稿者投稿内容
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2004-04-23 06:39
unibon です。こんにちわ。

Java でデスクトップアプリケーションを構築して運用していますが、プログラムのバグによる種々の RuntimeException やメモリ不足による OutOfMemoryError が発生した場合、コンソールにそっけなくスタックトレースがダンプされるだけです。
Java VM の起動に java(java.exe)を使えばそのようなダンプを表示できるコンソールがあるのでまだましですが、javaw(javaw.exe)を使うとそれさえ表示されなくなります。
要望としては、このような例外が発生した場面で、「不正な処理をおこないました」とか「ご迷惑をおかけしてすみません」のようなメッセージを、ダイアログボックス上に表示したいのですが、そのようなことはできるでしょうか。

もちろん、すべての個所に
コード:
try {
    ...
} catch (Throwable t) {
    JOptionPane.showMessageDialog(...);
}


のように書けば達成できますが、すべての個所に書くのは大変です。たんに個所が多くて大変というだけではなく、個別に書くのは奇麗ではないとも感じます。こういう場面で一括しておこなう処理を登録しておくようなことはできないのでしょうか。
Kissinger
ぬし
会議室デビュー日: 2002/04/30
投稿数: 428
お住まい・勤務地: 愛知県
投稿日時: 2004-04-23 08:26
unibonさん、こんにちは。

初心者が書いたプログラムを見ると、例外が起こる可能性があるところでは
全て、try〜catchやっているものを見かけます。私も最初はそうでした。

当然、catchが多くなりますし、エラーリカバリーが複雑になります。
メッセージを表示した後、終了してしまうプログラムなら簡単ですが、
実用的なアプリでは、そのあと意味のある処理を続けられなければなり
ませんから。

例外は発生したら一刻も早く catchしてしまうのではなく、適切な呼び出し元まで
遡って catchするようにメソッドに throwsを付ける方法もあります。
これなら、throwsが沢山必要になりますが、やたらと catchする必要が
なくなり、しかも、エラーリカバリーが簡単になることが多いです。

どの呼び出しレベルで catchするべきか検討するには、エラーメッセージを表示し
たあと最小限の犠牲と負担で処理を続けられる箇所です。

最近、例外処理を楽にするためにアスペクト指向を用いることもありますが、
あまり歓心できません。 まず、catchするレベルを充分設計することが大切
だと私は思っております。

unibonさんが知りたいこととはずれてしまったかも知れませんが。
ふーばー
大ベテラン
会議室デビュー日: 2003/06/05
投稿数: 163
投稿日時: 2004-04-23 09:13
コード:
main(String[] args) {
  try {
    ...
  } catch (Exception e) {
    // 適切なメッセージダイアログを表示
  }
}



ではだめですか?
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2004-04-23 09:14
unibon です。こんにちわ。

引用:

Kissingerさんの書き込み (2004-04-23 08:26) より:
メッセージを表示した後、終了してしまうプログラムなら簡単ですが、
実用的なアプリでは、そのあと意味のある処理を続けられなければなり
ませんから。


ありがとうございます。書き足りませんでしたが、今回の私の要望としては、エラーリカバリーは要らず、終了してしまって構いません。終了間際にダイイングメッセージを、目立つように残したいのです。ちなみにコンソールに出るスタックトレースだけだと、GUI のウィンドウの陰にあるので見逃されてしまうことがあります。
そもそも GUI のプログラムでは、RuntimeException 等が出ても、それはたとえば JMenuItem に対して addActionListener された ActionListener 内の処理なので、プログラムがすべて終了すらしないです。そのイベントハンドラのみが中断されるだけになってしまいます。
結局、要望を細かく書くと2点あり、(1)もう継続せずに終了してほしいこと、(2)終了間際にメッセージを目立つようにダイアログボックスで表示したい、の2点の機能がほしいのです。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2004-04-23 09:20
unibon です。こんにちわ。

引用:

ふーばーさんの書き込み (2004-04-23 09:13) より:
コード:
main(String[] args) {
  try {
    ...
  } catch (Exception e) {
    // 適切なメッセージダイアログを表示
  }
}



ではだめですか?


ありがとうございます。GUI を持ったデスクトップアプリケーションの場合は、main スレッドはアプリケーションの起動後にすぐに消滅してしまい、通常は AWT-EventQueue-0 などという名前の GUI スレッドが処理の中核になるので、このやりかたでは catch できないのです。
では、AWT-EventQueue-0 というスレッドで、上記と同様に catch すれば良いのかな、とも思い付きましたが、どこに catch を埋め込むことができるのか、で悩んでしまいました。
sauce
常連さん
会議室デビュー日: 2003/11/12
投稿数: 24
投稿日時: 2004-04-23 09:26
質問の意図が掴めなくて恐縮ですが…

「すべての個所」ってどこの事ですか?
デスクトップアプリでダイアログを出したい
→という事はGUI付アプリ
 →という事はMVCモデルで作られている
  →ならControllerで …}catch(Error){…}catch(RuntimeException){…} すればいい
という思考が働いたのですが、個所が多いという事は、多分これは的外れなんですよね。
Controllerって普通そんなに数が多い物ではないし。
となると、すべての個所とは何処の事を指しているのかな、と。


ちなみに、ソースコード中に全く例外処理を書かずに例外をハンドリングする方法として、jdbが使えます
が、これを利用してダイアログを出せるかと言うと、出来ない気が (^^;
sauce
常連さん
会議室デビュー日: 2003/11/12
投稿数: 24
投稿日時: 2004-04-23 09:40
#おや、入れ違った

もしや、統一的なControllerが無い、ViewとModelが密結合した構造ですか?
そうなると確かに「個所が多い」ですね…

ところで先程提示したリンク先のサイトでmonitorコマンドなる物が紹介されてますが、
これは使えませんかね?
お犬様
ベテラン
会議室デビュー日: 2003/01/26
投稿数: 67
投稿日時: 2004-04-23 10:30
JDK 1.5 で
Thread.setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler)
Thread.setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler)
等を使うのが一番良いのではないでしょうか。

1.4以前の場合だと、標準エラー出力には例外のスタックトレースしか出力しない、と決めておいて、スタックトレースを受け取り、その内容をダイアログに表示した後に強制終了するような OutputStream なりを作って System#setErr(java.io.PrintStream) するとかしか思いつきません。

スキルアップ/キャリアアップ(JOB@IT)