この方法で実際に改善できるのは、基本的にGUIアプリケーションで、また、バックグラウンドで動作するバッチのようなプログラムも対象となります。コンソールウィンドウを必要とする、対話式のCUIアプリケーションは対象外となりますので注意してください。
あと、Windows中心に解説していることにも注意してください。以下のファイルには、Windows用のサンプルソースとバイナリが含まれています。
サンプル (55.90 KB)
Javaのデスクトップアプリケーションは、とにかく起動に時間がかかります。これは、起動するたびにJavaVMが初期化を行うコストが大きいからです。ならば、起動したVMを使いまわすことができれば、これを解消できるのではないか、つまり、JavaVMを常駐させる方法があれば改善できる、と考えました。
しかし、今のところ、JavaVMそのものを常駐化する標準的な方法は見つかりませんでした(将来的に、VMの機能として導入されるかもしれないようですが)。ただし、JavaVMそのものではありませんが、Javaアプリケーションとしてなら実現できそうな方法がありました。
JDenginE (Java Desktop Engine) (リンク先を開く)
JDenginEは、Javaアプリケーションで、XML-RPC
サーバ(XML-RPC
についてはここを参照)として機能します。XML-RPC
を経由してアプリケーション起動リクエストを受信し、アプリケーションを代理で起動します。サーバ側で起動するので、最初に述べているように、標準入出力を必要とするCUIアプリケーションでは使えません(不可能というわけではなく、使い物にならないということ)。
Windows以外ではちゃんと試していないので、はっきりしたことは言えませんが、とにかくクライアントはXML-RPC
をサポートしている言語なら何でも良いということです。本体に付属しているのはPythonのスクリプトなので、これを他の言語に移植すれば良いのです。
注意すべき点として、JDenginEサーバはポート8080を使用します。これは、良く使われるポート番号なので、他のサービスなどが使用していないか確認してください。
高速化という点だけで言えば、JDenginEを使うだけで目的は果たすことができます。しかしながら、現バージョン(2005.05.21時点で 0.8)では、いくつか不便な点があります。特に、Windowsで使うにはやや面倒です。おそらくJDenginEの開発にはLinuxが使われたのでしょう。将来のバージョンでは、Windowsのための機能がサポートされるようです(次のリリースでは、インストーラを導入するとか、Windowsの「サービス」として起動できるようにする、などと書かれています)。
まず、サーバの起動とサーバとの通信を行うスクリプトが、それぞれBourne-ShellとPythonで書かれています。cygwinが載っているPCなら問題ないかもしれませんが、JREが使えるPCの数に較べて明らかに少数でしょう。
あと、これはバグなのかもしれませんが、クラスパスの区切り文字にWindowsでもコロン(:)を指定する必要があります。絶対パスで指定したい場合にはちょっと不便です。ドライブが1つで良いなら、ドライブレターを省けば事足ります。
サーバの起動方式は、将来機能強化されることが約束されているので、ここでは単に移植するにとどめておきます。startup.shでやっていることを、startup.batに移植します。(サンプルを参照)
クライアントは、なるべくどの環境でも使えるようにするため、cygwinが入っていない、かつ、デスクトップ上から実行するのを前提とします。また、いずれもDOSウィンドウを開かないようにします。また、XML-RPC
をサポートしている言語なら、と言いましたが、XML-RPCのライブラリを追加するのも面倒なので、標準のHTTP通信機能だけでやってみます。XMLとして扱うのは面倒ですが、JDenginEだけに限定すれば、パターンはそれほど多くはありません。以下は、サーバに送信する内容について記述しています。
JDenginEサーバへのリクエスト内容
ホスト 127.0.0.1(localhost) のポート8080に HTTPのPOSTメソッドで以下のXML文字列を送信 - 起動リクエストの場合 <?xml version="1.0"?> <methodCall> <methodName>JavaLauncher.Launch</methodName> <params><param> <value>[クラスパス] [起動クラス] [アプリケーションに渡す引数]</value> </param></params> </methodCall> - サーバのシャットダウンの場合 <?xml version="1.0"?> <methodCall> <methodName>JavaLauncher.Shutdown</methodName> </methodCall>
さて、Javaのページなので、Javaで作るのが筋とは思いますが、そもそも、Javaの起動速度を改善するためにやっているのですから、わざわざ別のJavaアプリケーションを起動してしまっては元の木阿弥です。というわけで、クライアントはネイティブコードのプログラムとして実装しました(JDenginE.Client.exe : サンプルを参照)。このプログラムのショートカットを作って、そのプロパティの「リンク先」の欄に次のように文字列を入力します。
JDenginEクライアント ショートカットのプロパティ-リンク先 の設定
JDenginE.Client.exeの絶対パス [クラスパス] [起動クラス] [アプリケーションに渡す引数]
※例の通りに半角スペースを入れること。絶対パスは元々設定されているもので良い。
このショートカットを実行すれば、指定したJavaアプリケーションが起動します。
サーバはバックグラウンドで動作しているので、終了させるにはプロセスを直接終了させる必要があります。これが面倒なら、終了をリクエストするようにします。先のクライアントプログラムで、次のように設定します。
JDenginEクライアント シャットダウン用の設定
JDenginE.Client.exeの絶対パス Shutdown
このショートカットを実行すると、起動中のJDenginEサーバが自らシャットダウンします。
System.exit()
を使わないようにしてください。サーバを起動しているJavaVM自体が終了してしまいます。J2SDK 1.4.0
以上となっていますが、アプリケーションの起動だけなら1.3.1
でも動作します。実際に試した感じでは、1.3.1
の方が格段に速く起動するようです。J2SE1.4
以降では、JFrame
やJDialog
のdispose()
メソッドを使ってアプリケーションを終了させることができますが、1.3.1
以前の場合は、dispose()
を実行してもアプリケーションが終了しないため、System.exit()
で終了させている場合が多いという点に注意してください。また、System.exit()
を使っていないアプリケーションでも、スレッドの使い方によってはうまく終了できないこともありますので注意してください。将来、標準のJavaVMが常駐できるようになれば、特別なことをしなくても高速に起動するようになるかも知れません。しかし、この方法を使えば、限定されてはいるものの、それがすぐに実現できます。これによって、Javaで書かれたデスクトップアプリケーションは、弱点のひとつが克服され、利用価値が一層向上することでしょう。
どれだけ実用に耐えるのか、今後も継続して実験していく予定です。
最終更新日 : 2005.05.29
copyright 2000-2005
ARGIUS project