如何检测哪种JRE安装 – 32位与64位

在使用NSIS安装程序进行安装期间,我需要检查系统上安装了哪个JRE(32位和64位)。 我已经知道我可以检查系统属性“ sun.arch.data.model ”,但是这是Sun特有的。 我想知道是否有一个标准的解决scheme。

正在使用的JVM体系结构可以使用“ os.arch ”属性进行检索:

 System.getProperty("os.arch"); 

“os”部分似乎有点不恰当,或者原来的devise者可能不希望JVM运行在没有写入的架构上。 返回值似乎不一致 。

NetBeans安装程序团队正在解决 JVM vs OS体系结构的问题 。 引用:

x64位:Java和System

跟踪问题143434 。

目前我们使用x64位的JVM来确定系统(以及Platform.getHardwareArch())是否为64位。 这是绝对错误的,因为可以在64位系统上运行32位JVM。 如果在32位JVM上运行,我们应该find一个解决scheme来检查操作系统真正的64位。

  • 对于Windows,可以使用WindowsRegistry.IsWow64Process()
  • 对于Linux – 通过检查'uname -m / -p'== x86_64
  • 对于Solaris,可以使用例如'isainfo -b'
  • 对于Mac OSX,它不能使用uname参数来完成,可能可以通过创build64位二进制文​​件并在平台上执行来解决…(不幸的是,这不起作用:(我只用x86_64创build了二进制文件和ppc64拱,它成功地执行在老虎..)
  • 对于通用的Unix支持 – 它不是很清楚…可能检查相同的'uname -m / -p'/'getconf LONG_BIT'并将其与一些可能的64位值(x86_64,x64,amd64,ia64 )。

所有运行在64位Ubuntu 8.0.4上的不同JVM的示例属性:

32位IBM 1.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位Sun 1.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位GNU 1.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来包装Java桌面应用程序。 所以我不仅需要检测任何JRE,而且Launch4j会使用它的searchalgorithm。 唯一有意义的方法是在NSIS安装程序中运行一个简短的Java程序。 这是Java:


    公共类DetectJVM {
        私人静态最终的string键[] = {
             “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){
                 String property = System.getProperty(key);
                如果(打印)System.out.println(键+“=”+属性);
                 if(property!= null){
                     int errCode =(property.indexOf(“64”)> = 0)?  64:32;
                    如果(打印)System.out.println(“err code =”+ errCode);
                     System.exit(ERRCODE);
                 }
             }
         }
     }

用Launch4J把它包起来。 使用GUI标题types,但也设置为true。 否则,错误代码将会丢失。 (我把这一切都放在我的Netbeans Ant构build脚本中。

这是使用它的匹配的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位AMD DLL。
    转到DoneX64
 NotX64:
    文件... 32位x86 DLL。
 DoneX64:
删除$ INSTDIR \ detectjvm.exe

这在WinXP的很多种机器上都运行良好,没有SP,通过Vista和Win7,所有的SP都是32位和64位。

请注意,在我的NSIS脚本中,我正在使用一个现有的程序包来检查JVM是否已安装并首先执行,因此默认的32位select只会在JVM安装出现问题时才会发生,在这种情况下无论如何,您复制的DLL集合都无关紧要。

希望这对某人有帮助。

在编写Java代码时,如何区分32位和64位操作?

http://www.oracle.com/technetwork/java/hotspotfaq-138619.html#64bit_detection

没有公共的API可以让你区分32位和64位操作。 把64位看作是一次写入的另一个平台,随处运行传统。 但是,如果您想要编写特定于平台的代码(对您不利),则系统属性sun.arch.data.model的值为“32”,“64”或“unknown”。

 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()); } } 

在linux上,my(java)vm报告java.vm.name = Java HotSpot(TM)64位服务器虚拟机。 系统的javadocs声明System.getProperty将始终有一个值,但沉默sun.arch.data.model。

不幸的是,他们没有指定系统属性是什么,所以其他一些JVM可能会报告java.vm.name = Edgar。

顺便说一下,通过“安装在系统上”,我假设你的意思是“当前运行的JVM”?

在系统上可能有32位和64位的JVM,并且其中很多。

如果你已经有了每个受支持的平台的dll,可以考虑制作一个链接和运行的小型可执行文件,以便testing平台是否支持给定的function。 如果可执行文件链接并运行,则可以安装相应的共享库。

如果你有你要检查的.exe的path,你可以使用这个答案 。 基本上它只是查看.exe文件中的头文件,并告诉您在Windows上是否是64位或32位。

 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) 

以下代码检查任何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; } } 

请注意,为简洁起见,代码已被压缩。