NSIS インストーラーを使用したインストール中に、システムにインストールされている JRE (32 ビットと 64 ビット) を確認する必要があります。システム プロパティ " " をチェックできることは既に知っていますsun.arch.data.model
が、これは Sun 固有のものです。これに対する標準的な解決策があるかどうか疑問に思っています。
9 に答える
使用中のJVMアーキテクチャは、「 os.arch」プロパティを使用して取得できます。
System.getProperty("os.arch");
「os」の部分は少し誤称のようです。あるいは、元の設計者は、JVMが作成されていないアーキテクチャで実行されることを期待していなかったのかもしれません。戻り値に一貫性がないようです。
NetBeansインストーラチームは、JVMとOSのアーキテクチャの問題に取り組んでいます。引用:
x64ビット:Javaおよびシステム
問題143434として追跡されます。
現在、JVMのx64ビットを使用して、システム(したがって、Platform.getHardwareArch())が64ビットであるかどうかを判断しています。64ビットシステムで32ビットJVMを実行できるため、これは間違いなく間違っています。32ビットJVMで実行している場合、OSの実際の64ビット性をチェックするための解決策を見つける必要があります。
- Windowsの場合、WindowsRegistry.IsWow64Process()を使用して実行できます。
- Linuxの場合-'uname-m / -p'==x86_64をチェックします
- Solarisの場合、たとえば「isainfo-b」を使用して実行できます。
- Mac OSXの場合、uname引数を使用して実行することはできません。おそらく、64ビットバイナリを作成してプラットフォームで実行することで解決できます...(残念ながら、これは機能しません:(私はx86_64でのみバイナリを作成しましたおよびppc64archであり、Tigerで正常に実行されました。)
- 一般的なUnixサポートの場合-それも明確ではありません...同じ'uname-m / -p' /'getconf LONG_BIT'をチェックし、いくつかの可能な64ビット値(x86_64、x64、amd64、ia64)と比較する可能性があります)。
すべて64ビットUbuntu8.0.4で実行されているさまざまなJVMのサンプルプロパティ:
32ビットIBM1.5:
java.vendor=IBM Corporation
java.vendor.url=http://www.ibm.com/
java.version=1.5.0
java.vm.info=J2RE 1.5.0 IBM J9 2.3 Linux x86-32 j9vmxi3223-20061001 (JIT enabled)
J9VM - 20060915_08260_lHdSMR
JIT - 20060908_1811_r8
GC - 20060906_AA
java.vm.name=IBM J9 VM
java.vm.specification.name=Java Virtual Machine Specification
java.vm.specification.vendor=Sun Microsystems Inc.
java.vm.specification.version=1.0
java.vm.vendor=IBM Corporation
java.vm.version=2.3
os.arch=x86
os.name=Linux
os.version=2.6.24-23-generic
sun.arch.data.model=32
64ビットSun1.6:
java.vendor=Sun Microsystems Inc.
java.vendor.url=http://java.sun.com/
java.vendor.url.bug=http://java.sun.com/cgi-bin/bugreport.cgi
java.version=1.6.0_05
java.vm.info=mixed mode
java.vm.name=Java HotSpot(TM) 64-Bit Server VM
java.vm.specification.name=Java Virtual Machine Specification
java.vm.specification.vendor=Sun Microsystems Inc.
java.vm.specification.version=1.0
java.vm.vendor=Sun Microsystems Inc.
java.vm.version=10.0-b19
os.arch=amd64
os.name=Linux
os.version=2.6.24-23-generic
sun.arch.data.model=64
64ビットGNU1.5:
java.vendor=Free Software Foundation, Inc.
java.vendor.url=http://gcc.gnu.org/java/
java.version=1.5.0
java.vm.info=GNU libgcj 4.2.4 (Ubuntu 4.2.4-1ubuntu3)
java.vm.name=GNU libgcj
java.vm.specification.name=Java(tm) Virtual Machine Specification
java.vm.specification.vendor=Sun Microsystems Inc.
java.vm.specification.version=1.0
java.vm.vendor=Free Software Foundation, Inc.
java.vm.version=4.2.4 (Ubuntu 4.2.4-1ubuntu3)
os.arch=x86_64
os.name=Linux
os.version=2.6.24-23-generic
(GNUバージョンは「sun.arch.data.model」プロパティを報告しません。おそらく他のJVMも報告しません。)
NSISとLaunch4jを使用してJavaDesktopアプリをラップしています。したがって、JREを検出するだけでなく、Launch4jが検索アルゴリズムで検出する必要があります。理にかなっている唯一のアプローチは、NSISインストーラー内で短いJavaプログラムを実行することです。これがJavaです:
パブリッククラスDetectJVM{ プライベート静的最終文字列キー[]={ "sun.arch.data.model"、 "com.ibm.vm.bitmode"、 「os.arch」、 }; public static void main(String [] args){ boolean print = args.length> 0 && "-print" .equals(args [0]); for(String key:keys){ 文字列プロパティ=System.getProperty(key); if(print)System.out.println(key + "=" + property); if(property!= null){ int errCode =(property.indexOf( "64")> = 0)?64:32; if(print)System.out.println( "err code =" + errCode); System.exit(errCode); } } } }
これをLaunch4Jでラップします。GUIヘッダータイプを使用しますが、trueに設定します。そうしないと、エラーコードが失われます。(これをすべてNetbeansAntビルドスクリプトに入れました。
これを使用する一致するNSISコードは次のとおりです。
ファイル ... ; detectjvm.exeを含むファイルを解凍します。 ClearErrors ExecWait'"$ INSTDIR \ detectjvm.exe"' $ 0 IfErrors DetectExecError IntCmp $ 0 0 DetectError DetectError DoneDetect DetectExecError: StrCpy $0"実行エラー" DetectError: MessageBox MB_OK "JVMアーキテクチャ($ 0)を判別できませんでした。32ビットを想定しています。" NotX64に移動 DoneDetect: IntCmp $ 0 64 X64 NotX64 NotX64 X64: ファイル...64ビットAMDDLL。 後藤DoneX64 NotX64: ファイル...32ビットx86DLL。 DoneX64: $ INSTDIR\detectjvm.exeを削除します
これは、SPのないWinXPからVistaまで、および32ビットと64ビットのすべてのSPを備えたWin7まで、非常に多種多様なマシンで正常に機能しました。
私のNSISスクリプトでは、JVMがインストールされているかどうかを確認し、それを最初に実行する既存のパッケージを使用しているため、デフォルトの32ビット選択は、JVMのインストールで問題が発生した場合にのみ発生します。コピーするDLLのセットはとにかく重要ではありません。
これが誰かに役立つことを願っています。
Javaコードを作成する場合、32ビット操作と64ビット操作をどのように区別しますか?
http://www.oracle.com/technetwork/java/hotspotfaq-138619.html#64bit_detection
32ビット操作と64ビット操作を区別できるパブリックAPIはありません。64ビットは、1回の書き込みで、従来のどこでも実行できる別のプラットフォームと考えてください。ただし、プラットフォーム固有のコードを記述したい場合(恥ずべきことです)、システムプロパティsun.arch.data.modelの値は「32」、「64」、または「不明」です。
import sun.misc.*;
import java.lang.reflect.*;
public class UnsafeTest {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe) unsafeField.get(null);
System.out.println(unsafe.addressSize());
}
}
java -version
64 ビットの Java バージョンの場合、次のように出力されます。
java version "1.8.0_92"
Java(TM) SE Runtime Environment (build 1.8.0_92-b14)
Java HotSpot(TM) ***64-Bit*** Server VM (build 25.92-b14, mixed mode)
32ビットの場合、それはちょうど
java version "1.8.0_92"
Java(TM) SE Runtime Environment (build 1.8.0_92-b14)
Java HotSpot(TM) Client VM (build 25.92-b14, mixed mode)
Linuxでは、私の(java)vmはjava.vm.name = Java HotSpot(TM)64ビットサーバーVMを報告します。Systemのjavadocsは、System.getPropertyが常にこの値を持つことを宣言していますが、sun.arch.data.modelではサイレントです。
残念ながら、システムプロパティが指定されていないため、他のJVMがjava.vm.name=Edgarを報告するだけの場合があります。
ところで、「システムにインストールされている」とは、「現在実行中のJVM」を意味していると思いますか?
システムには 32 ビットと 64 ビットの両方の JVM があり、それらはたくさんあります。
サポートされているプラットフォームごとに dll が既にある場合は、プラットフォームが特定の機能をサポートしているかどうかをテストできるように、リンクして実行する小さな実行可能ファイルを作成することを検討してください。実行可能ファイルをリンクして実行すると、対応する共有ライブラリをインストールできます。
確認したい .exe へのパスがある場合は、この回答を使用できます。基本的には、.exe ファイルのヘッダーを確認するだけで、Windows で 64 ビットか 32 ビットかがわかります。
次のコードは、Windows 実行可能ファイルの machineType フィールドをチェックして、32 ビットか 64 ビットかを判断します。
public class ExeDetect
{
public static void main(String[] args) throws Exception {
File x64 = new File("C:/Program Files/Java/jre1.6.0_04/bin/java.exe");
File x86 = new File("C:/Program Files (x86)/Java/jre1.6.0/bin/java.exe");
System.out.println(is64Bit(x64));
System.out.println(is64Bit(x86));
}
public static boolean is64Bit(File exe) throws IOException {
InputStream is = new FileInputStream(exe);
int magic = is.read() | is.read() << 8;
if(magic != 0x5A4D)
throw new IOException("Invalid Exe");
for(int i = 0; i < 58; i++) is.read(); // skip until pe offset
int address = is.read() | is.read() << 8 |
is.read() << 16 | is.read() << 24;
for(int i = 0; i < address - 60; i++) is.read(); // skip until pe header+4
int machineType = is.read() | is.read() << 8;
return machineType == 0x8664;
}
}
コードは簡潔にするために圧縮されていることに注意してください...