WebstartアプリケーションでSystem.exit()を明示的に呼び出す必要がありますか?
-
03-07-2019 - |
質問
最近、SwingアプリケーションをWebstartに変換しました。プロセスは非常に簡単でしたが、すべてのウィンドウを閉じた後、アプリケーションのJVMが終了しないことがわかりました。スレッドダンプは、2つの非デーモンスレッド、特にSwingのEDT、AWT、およびいくつかのwebsart関連のスレッドがあることを示しました。
実際に使用される戦略は、各ウィンドウが作成されるとカウンターを増やし、閉じられるとカウンターを減らすことです。デフォルトのクローズ操作はDISPOSE_ON_CLOSEです。カウンターがゼロになったら、すべてのスレッドプールを停止し、すべてのJNIリソースを解放します。
batファイル(同じJAR)からアプリケーションを起動したとき、すべてのウィンドウが閉じられたときに正常に終了したため、問題はWebstartと関係があることがわかりました。
次の質問:
- 誰が正確に何が起こっているのか教えてもらえますか? WebstartがゾンビJVMを残すのはなぜですか?
- JVMを停止せずにWebstartリソースを明示的に解放する方法はありますか?
- System.exit()を呼び出すと、リソースを解放せず、OSに依存してクリーンアップするというずさんなプラクティスを奨励するという意見が常にありました(後でコードを再利用すると、厄介な驚きにつながる可能性があります) ...何か不足していますか?
解決
WebStartのバグのため、はい。 WebStartは「セキュアスレッド」を起動します。 EDTと対話するのはそれ自身の目的のためです。このSecureThreadは、すべてのウィンドウとAWTリソースが破棄されたときに予期されるJavaプロセスの自動終了を防ぎます。
他のヒント
通常、AWT EDTが原因です。ここ数年、廃棄されていないウィンドウがない場合にシャットダウンするロジックがありました。ただし、AWTおよびSwingの実装内を含め、リークには繰り返し問題があります。そのため、本番リリースでSystem.exitを使用することを強くお勧めします(リークを検出するためのテストのためにSystem.exitを残すこともできます)。
システムウィンドウ(コンソール、javax.jnlpサービス、およびその他のダイアログ)が表示されていない場合、WebStartスレッドはすべてデーモンである必要があります。
Webstartはコンソールウィンドウを起動します(無効にすることができる場合があります)。コンソールウィンドウは、webstartプロセスのstdout / errと基本的なログ/デバッグを確認するために使用されますが、トップレベルのAWT / Swingウィンドウを作成するという副作用があります。 AWT / EDTはLASTウィンドウが破棄されたときにのみ終了するため、コンソールウィンドウはアプリケーションを保留しています。 System.exit()を呼び出して、アプリケーションが終了することを100%確認する必要があります(特定のクライアント構成を保証できない限り、webstartコンソールはオフになります)
jconsoleでアタッチすることを検討し、JVMの動作を確認してください。
Webスタートでも同じ問題が発生します。 Javaコンソールをオフにしても、プロセスはハングアップしません。 Sunからの既知のバグID