- はじめに
- JDK7(あるいはそれ以前の)インストール時の挙動
- JDK8(あるいはそれ以降の)インストール時の挙動
- Java Runtime Environment \ CurrentVersion
- Windows サービス起動する Java アプリの場合話しがややこしくなる
- Java7 と Java8 では MaxTenuringThreshold の上限も違う
はじめに
Windows 環境での話し。
いまさらの話し。
Java7 と Java8 でライタイムの配備方法が変更され、以下のエラーで起動できないことがある。
Error: Registry key 'Software\JavaSoft\Java Runtime Environment'\CurrentVersion' has value '1.8', but '1.7' is required.
特にサービスから起動する Javaアプリケーションは注意が必要。
JDK7(あるいはそれ以前の)インストール時の挙動
JDK 7のインストール時にパブリックJREが Windows\System32
にコピーされる。具体的には java.exe
, javaw.exe
, javaws.exe
がコピーされる。
32 bit 版をインストールした場合は Windows\SysWOW64
にコピーされる。WOW64 は Windows 32-bit On Windows 64-bit で、32 bit 版のバイナリが入っており実行時には 64 bit にエミュレートされる。System32 側は名前に反して64 bit バイナリが入ることになる。
Windows\System32
に java.exe
が入るので、環境変数として別途 PATH
を通すことなく Java が利用できるようになる。という開発者視点から見るとおせっかいな方法が取られている。
JDK8(あるいはそれ以降の)インストール時の挙動
JDK 8 のインストール時には「システム環境変数」(ユーザー環境変数ではない) PATH
の先頭にC:\ProgramData\Oracle\Java\javapath;
が追加される。そしてこの位置に java.exe
, javaw.exe
, javaws.exe
がコピーされる。
PATH
の定義中に C:\ProgramData\Oracle\Java\javapath;
が存在しなければ先頭に追加し、存在すれば追加しないという挙動になる。
通常は C:\Windows\System32;
よりも C:\ProgramData\Oracle\Java\javapath;
が先頭にくるため、 java.exe
は C:\ProgramData\Oracle\Java\javapath;
にある Java8 のものが優先的に利用されることになる。
Java Runtime Environment \ CurrentVersion
システム中の Java の現在のバージョンは以下のキーのレジストリ値として設定されている。
HKEY_LOCAL_MACHINE\Software\JavaSoft\Java Runtime Environment'\CurrentVersion
この値が 1.7
とか 1.8
とか設定される。
そして、先に見た C:\Windows\System32;
や C:\ProgramData\Oracle\Java\javapath;
にコピーされた java.exe
は起動時にレジストリ中の現在バージョンとのチェックを行う。
レジストリの現在バージョンに 1.8
が設定されていた場合、Windows\System32\java.exe
つまり1.7の java.exe を実行すると以下のようなエラーになり実行できない。
Error: Registry key 'Software\JavaSoft\Java Runtime Environment'\CurrentVersion' has value '1.8', but '1.7' is required.
逆にレジストリに 1.7
が設定されており、C:\ProgramData\Oracle\Java\javapath
側の 1.8 の java.exe を実行した場合も同様にエラーになり実行できない。
Error: Registry key 'Software\JavaSoft\Java Runtime Environment'\CurrentVersion' has value '1.7', but '1.8' is required.
CurrentVersion
とのチェックを行うのは、C:\Windows\System32
やC:\ProgramData\Oracle\Java\javapath
にコピーされた java.exe
だけで、C:\Program Files\Java\jdk1.X.X\bin\java.exe
を直接指定した場合にはチェックは行われずエラーにはならない。
Windows サービス起動する Java アプリの場合話しがややこしくなる
Java7 と Java8 が共存するケースで Windows のサービスからパス指定なしの java.exe コマンドを起動した場合は以下のエラーに直目することになる。
Error: Registry key 'Software\JavaSoft\Java Runtime Environment'\CurrentVersion' has value '1.8', but '1.7' is required.
サービス起動した場合のアカウントは(アカウントを特に指定しない場合)SYSTEMアカウントとなり、システム環境変数が読み込まれる(ユーザ環境変数ではない)。
ちなみにシステム環境変数を変更した後は、再起動しないとサービス起動時のシステム環境変数に反映されない。Services.exe の環境変数はシステム起動時に読み込まれ、サービスの起動は Services.exe から環境変数を引き継ぐためとなる。
システム環境変数の PATH
には、つまりC:\ProgramData\Oracle\Java\javapath
が先頭にあれば 1.8 が使われる。
しかし、サービス起動時のカレントディレクトリはC:\Windows\System32
であり、ここに直接コピーされた java.exe
が優先的に使われてしまう。
これにより 1.7 の java.exe
が起動し、レジストリの CurrentVersion
に設定された 1.8 との違いによりエラーとなり起動できなくなってしまう。
サービス起動時の java を明示的にパス指定しても良いが、C:\Windows\System32
にコピーされた java.exe
, javaw.exe
, javaws.exe
を削除して、切り替えたい場合はJAVA_HOME
など PATH
の設定でなんとかする方が良い。
そもそもC:\Windows\System32
に直接コピーなんて気持ち悪いので早い目に消し去ってあげたい。
Java7 と Java8 では MaxTenuringThreshold の上限も違う
ついでの話し。
Java8 になって Permanent領域 が無くなり Nativeメモリ側に Metaspace として定義されるようになったので、Permanent領域の VM オプションは非推奨でワーニングになる。
Java7 | Java8 |
---|---|
-XX:PermSize | -XX:MetaspaceSize |
-XX:MaxPermSize | -XX:MaxMetaspaceSize |
のは有名な話し。
Java8では -XX:MaxTenuringThreshold
の値が 0 ~15 では無い場合にエラーとなり起動出来なくなった。
Java5 だか Java6 だかの時代には 32 がデフォルトだったが、この値を明示的に指定していた場合には Java8 にすると JVM が起動できなくなる。
パラレル(スループット)コレクタの場合 15 で、CMSコレクタの場合 6 がデフォルト値。あえて指定する必要もないかな。
Javaプログラマーなら習得しておきたい Java SE 8 実践プログラミング
- 作者: Cay S. Horstmann
- 出版社/メーカー: インプレス
- 発売日: 2015/04/03
- メディア: Kindle版
- この商品を含むブログ (8件) を見る
Java 9 Modularity: Patterns and Practices for Developing Maintainable Applications (English Edition)
- 作者: Sander Mak,Paul Bakker
- 出版社/メーカー: O'Reilly Media
- 発売日: 2017/09/07
- メディア: Kindle版
- この商品を含むブログを見る