torutkのブログ

ソフトウェア・エンジニアのブログ

launch4jを使ってexe化したJavaプログラムが、あるWindows機で実行できない

衛星の位置と軌道を表示するプログラムJSatTrak - torutkのブログで、同じくlaunch4jでexe化したJavaプログラム(JSatTrak)が起動しないというエラーがありました。

同じマシンで、FreeMindを起動しようとしたときに、同じエラーが発生しました。FreeMindも、launch4jを使ってexe化されていまあす。

別なWindows 10マシンで確かめてみたところ、こちらはどちらも正常に起動できました。
http://www.torutk.com/issues/6#note-11

そこで、launch4jがどのようにレジストリをアクセスしてjava.exeを呼び出しているのかを調査しました。調査には、プロセスのファイルアクセス、レジストリアクセス、プロセスやスレッドの使用を監視するprocmon.exe(MicrosoftのSysInternalsSuitesに含まれるツール)を使います。

procmon.exeを起動します。デフォルトでは全プロセスの全活動が表示されてしまうので、FreeMind.exeのレジストリ活動だけを監視するようフィルタを設定しました。

  • [Filter]メニュー > [Filter..]で、次の3つのアイテムを追加しました。
    • Commad Line contains freemind
    • Operation contains reg
    • Path contains JavaSoft

プロセス名にfreemindが含まれるものを対象とし、そのプロセスの操作はレジストリアクセスでアクセスのパスにJavaSoftが含まれるものに限定しています。

FreeMind.exe(launch4jで作成したexe)を実行すると、procmonの画面上にレジストリアクセスの操作履歴が表示されます。

HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environmentの下にあるキーの名前を一通り取得し、そのなかにある1つを選択しているようです。
キーの名前では、1.7、1.7.0_80、1.8、1.8.0_141、1.8.0_152、1.8.0_60 とあり、この中から1.8.0_60を選択してそのJavaを使おうとしています。

  • 最新のレビジョンである1.8.0_152を使用せず、1.8.0の中では一番古い1.8.0_60を使用している

ところが、このマシンは、Java 8u141と8u152が入っていますが、8u60は入っていません。レジストリを見てみます。

Java Runtime Environment に1.8.0_60の設定が存在しています。しかし、この実体は存在していないので、過去に古いJava REのアンインストールに失敗したか、インストーラーを使わずディレクトリ削除したかと思われます。

そこで、レジストリから1.8.0_60を削除してみます。

するとFreeMindが立ち上がるようになりました。今度はJRE 1.8.0_152を使っています。

メモ

Javaのインストールディレクトリを探す場合、レジストリのHKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment のCurrentVersionの値を確認(現状は1.8)、次にレジストリのHKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\1.8 のJavaHomeの値を確認するのが流れです。

しかし、launch4jについては、CurrentVersion ではなく、自分でレジストリのキーを探し回り、何某かのロジックで使用するバージョンを決めています(文字列ソートしているか、1.8.0_の後ろは2桁を前提としている節があります)。