first-published: Sep 22 23:45, 2001
last-modified: July 2 13:00, 2002
メソッド呼び出しを含まないループを長時間実行している Java スレッドがあったとしましょう。他のスレッドから stop() された場合、ループから抜けなければなりません。と ころが、JIT コンパイラ、AOT コンパイラといった Java 処理 系が非同期例外を考慮していない場合、ループ実行中のスレッ ドは stop() されたことに気付けません。ここでそのループが 無限ループだった場合、本来は stop() されたことでループか ら抜けるところ、抜けずに永久にルー プを続けることになってしまいます。
Kaffe 1.0.6に含まれる test/regression/ThreadStop.java が、Java 処理系の Thread#stop() への対応具合を調べる格好 のテストプログラムとなっています。対応できている場合、 「All tests completed」と表示された後プログラムは終了す るのですが、対応できていない場合、表示後、プログラムはい つまでも終了しません。あるスレッドが stop() されたにも関 わらず止まらないので、処理系自体も終了しないのです。
通常、JIT, AOT コンパイラは「メソッド呼び出しから戻った 際に例外が throw されているかどうかチェックする」という コードを生成します。なので、ループの中にメソッド呼び出し がひとつでもあれば、ThreadDeath 例外、つまり stop() され たことを検出できます。しかしメソッド呼び出しがない場合、 例外チェックが行われない恐れがあります。無限ループの実行 中であっても、確実に stop() されたことに気付かせなければ なりません。
スレッドが自発的にポーリングするとどうしても性能は低下し ます。ポーリングといった同期的な (synchronous) 方法では なく、外からスレッドのコンテクストを操作する、シグナルを 利用する、といった非同期な (asynchronous) 方法も考えられ ます。
ただ、Thread#stop() で無限ループが止まらなくとも 現実に困る局面はまずありませんし、 ポーリングはある程度のオーバヘッドを導入し、 性能が低下してしまいます。Thread#stop() は deprecated メソッドですし、 対応しないという選択もアリだと思います。