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

时间:2009-04-30 14:41:02

标签: 64-bit 32-bit nsis java

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

9 个答案:

答案 0 :(得分:48)

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

System.getProperty("os.arch");

“os”部分似乎有点用词不当,或者原始设计师可能不希望JVM在他们不是为其编写的体系结构上运行。返回值似乎为inconsistent

NetBeans安装程序团队是JVM与操作系统体系结构的tackling the issue。引用:

  

x64位:Java和系统

     

跟踪为Issue 143434

     

目前我们使用x64位的JVM来   确定是否系统(因此   Platform.getHardwareArch())是64位   或不。这是绝对错误的   可以运行32位JVM   64位系统。我们应该找到一个   检查OS真实64位的解决方案   如果在32位JVM上运行。

     
      
  • 对于Windows,可以使用WindowsRegistry.IsWow64Process()
  • 来完成   
  • for Linux - 通过检查'uname -m / -p'== x86_64
  •   
  • 对于Solaris,可以使用例如'isainfo -b'
  •   
  • 对于Mac OSX,无法使用uname参数完成,可能是这样   通过创建64位二进制来解决   并在平台上执行......   (不幸的是,这不起作用:(   我只使用x86_64创建了二进制文件   和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

64bit 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也不报告。)

答案 1 :(得分:7)

我正在使用NSIS和Launch4j来封装Java桌面应用程序。因此,我不仅需要检测任何JRE,而且Launch4j将使用其搜索算法找到。唯一有意义的方法是在NSIS安装程序中运行一个简短的Java程序。这是Java:


    public class DetectJVM {
        private static final String keys [] = {
            "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);
                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。否则错误代码将丢失。 (我将所有这些都放在我的Netbeans Ant构建脚本中。

以下是使用它的匹配NSIS代码:


File ... ; unpack files including detectjvm.exe.
ClearErrors
ExecWait '"$INSTDIR\detectjvm.exe"' $0
IfErrors DetectExecError
IntCmp $0 0 DetectError DetectError DoneDetect
DetectExecError:
    StrCpy $0 "exec error"
DetectError:
    MessageBox MB_OK "Could not determine JVM architecture ($0). Assuming 32-bit."
    Goto NotX64
DoneDetect:
IntCmp $0 64 X64 NotX64 NotX64
X64:
    File  ... 64-bit AMD DLLs.
    Goto DoneX64
NotX64:
    File ... 32-bit x86 DLLs.
DoneX64:
Delete $INSTDIR\detectjvm.exe

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

请注意,在我的NSIS脚本中,我正在使用现有的包来检查JVM是否已安装并首先执行此操作,因此只有在JVM安装出现严重错误的情况下才会出现默认的32位选择,在这种情况下,你复制的DLL集合无论如何都无关紧要。

希望这对某人有帮助。

答案 2 :(得分:4)

编写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”。

答案 3 :(得分:1)

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

答案 4 :(得分:0)

在linux上,我的(java)vm报告java.vm.name = Java HotSpot(TM)64位服务器VM。 System的javadoc声明System.getProperty将始终具有此值,但对sun.arch.data.model保持沉默。

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

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

答案 5 :(得分:0)

系统上可能有32位和64位JVM,而且很多都是。

如果您已经为每个支持的平台配备了dll - 请考虑制作一个链接和运行的小型可执行文件,以便您可以测试该平台是否支持给定的功能。如果可执行文件链接并运行,则可以安装相应的共享库。

答案 6 :(得分:0)

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)

答案 7 :(得分:-1)

如果您有要检查的.exe的路径,则可以使用this answer。基本上它只是查看.exe文件中的标题,并告诉你在Windows上它是64位还是32位。

答案 8 :(得分:-5)

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

请注意,为简洁起见,代码已经过压缩......