简体   繁体   English

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

[英]How do I detect which kind of JRE is installed — 32bit vs. 64bit

During installation with an NSIS installer, I need to check which JRE (32bit vs 64bit) is installed on a system. 在使用NSIS安装程序进行安装期间,我需要检查系统上安装了哪个JRE(32位与64位)。 I already know that I can check a system property " sun.arch.data.model ", but this is Sun-specific. 我已经知道我可以检查一个系统属性“ sun.arch.data.model ”,但这是Sun特有的。 I'm wondering if there is a standard solution for this. 我想知道是否有一个标准的解决方案。

The JVM architecture in use can be retrieved using the " os.arch " property: 可以使用“ os.arch ”属性检索正在使用的JVM体系结构:

System.getProperty("os.arch");

The "os" part seems to be a bit of a misnomer, or perhaps the original designers did not expect JVMs to be running on architectures they weren't written for. “os”部分似乎有点用词不当,或者原始设计师可能不希望JVM在他们不是为其编写的架构上运行。 Return values seem to be inconsistent . 返回值似乎不一致

The NetBeans Installer team are tackling the issue of JVM vs OS architecture. NetBeans安装程序团队正在解决 JVM与操作系统体系结构的问题 Quote: 引用:

x64 bit : Java and System x64位:Java和系统

Tracked as the Issue 143434 . 跟踪问题143434

Currently we using x64 bit of JVM to determine if system (and thus Platform.getHardwareArch()) is 64-bit or not. 目前我们使用x64位的JVM来确定系统(以及Platform.getHardwareArch())是否为64位。 This is definitely wrong since it is possible to run 32bit JVM on 64bit system. 这绝对是错误的,因为可以在64位系统上运行32位JVM。 We should find a solution to check OS real 64-bitness in case of running on 32-bit JVM. 我们应该找到一个解决方案,以便在32位JVM上运行时检查OS真正的64位。

  • for Windows it can be done using WindowsRegistry.IsWow64Process() 对于Windows,可以使用WindowsRegistry.IsWow64Process()来完成
  • for Linux - by checking 'uname -m/-p' == x86_64 对于Linux - 通过检查'uname -m / -p'== x86_64
  • for Solaris it can be done using eg 'isainfo -b' 对于Solaris,可以使用例如'isainfo -b'来完成
  • for Mac OSX it can't be done using uname arguments, probably it can be solved by creating of 64-bit binary and executing on the platform... (unfortunately, this does not work:( I've created binary only with x86_64 and ppc64 arch and it was successfully executed on Tiger..) 对于Mac OSX,它无法使用uname参数完成,可能它可以通过创建64位二进制文​​件并在平台上执行来解决...(不幸的是,这不起作用:(我只用x86_64创建了二进制文件)和ppc64拱,它在Tiger上成功执行..)
  • for Generic Unix support - it is not clear as well... likely checking for the same 'uname -m/-p' / 'getconf LONG_BIT' and comparing it with some possible 64-bit values (x86_64, x64, amd64, ia64). 对于通用Unix支持 - 它也不清楚...可能检查相同的'uname -m / -p'/'getconf LONG_BIT'并将其与一些可能的64位值(x86_64,x64,amd64,ia64)进行比较)。

Sample properties from different JVMs all running on 64bit Ubuntu 8.0.4: 来自64位Ubuntu 8.0.4上运行的不同JVM的示例属性:

32bit IBM 1.5: 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: 64位太阳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

64bit GNU 1.5: 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

(The GNU version does not report the "sun.arch.data.model" property; presumably other JVMs don't either.) (GNU版本不报告“sun.arch.data.model”属性;可能其他JVM也没有。)

I'm using NSIS and Launch4j to wrap a Java Desktop app. 我正在使用NSIS和Launch4j来封装Java桌面应用程序。 So I need not only to detect any JRE, but the one Launch4j will find with its search algorithm. 因此,我不仅需要检测任何JRE,而且Launch4j将使用其搜索算法找到。 The only approach that made sense is to run a short Java program within the NSIS installer. 唯一有意义的方法是在NSIS安装程序中运行一个简短的Java程序。 Here's the 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);
                }
            }
        }
    }

Wrap this with Launch4J. 用Launch4J包装它。 Use the GUI header type but also set to true. 使用GUI标头类型但也设置为true。 Otherwise the error code will be lost. 否则错误代码将丢失。 (I put all this in my Netbeans Ant build script. (我将所有这些都放在我的Netbeans Ant构建脚本中。

Here's the matching NSIS code that uses it: 这是使用它的匹配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

This has worked fine on a very large variety of machines from WinXP with no SP through Vista and Win7 with all SPs, 32- and 64-bit. 这在WinXP的各种各样的机器上运行良好,没有SP通过Vista和Win7,所有SP,32位和64位。

Note that in my NSIS script I'm using an existing package that checks to see if the JVM is installed and does that first, so the default 32-bit selection would only occur if something went badly wrong with the JVM install, in which case the set of DLLs you copy won't matter anyway. 请注意,在我的NSIS脚本中,我正在使用现有的包来检查JVM是否已安装并首先执行此操作,因此只有在JVM安装出现严重错误的情况下才会出现默认的32位选择,在这种情况下你复制的DLL集无论如何都无关紧要。

Hope this is helpful to somebody. 希望这对某人有帮助。

When writing Java code, how do I distinguish between 32 and 64-bit operation? 编写Java代码时,如何区分32位和64位操作?

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

There's no public API that allows you to distinguish between 32 and 64-bit operation. 没有公共API允许您区分32位和64位操作。 Think of 64-bit as just another platform in the write once, run anywhere tradition. 将64位视为一次写入中的另一个平台,随处运行。 However, if you'd like to write code which is platform specific (shame on you), the system property sun.arch.data.model has the value "32", "64", or "unknown". 但是,如果您要编写特定于平台的代码(对您有羞耻感),则系统属性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());
  }
}
java -version

For a 64bit java version it'll print : 对于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)

For 32 bit it'll be just 对于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)

On linux, my (java) vm reports java.vm.name=Java HotSpot(TM) 64-Bit Server VM. 在linux上,我的(java)vm报告java.vm.name = Java HotSpot(TM)64位服务器VM。 The javadocs for System declare that System.getProperty will always have a value for this but are silent on sun.arch.data.model. System的javadoc声明System.getProperty将始终具有此值,但对sun.arch.data.model保持沉默。

Unfortunately they don't specify what the system property will be so some other JVM might just report java.vm.name=Edgar. 不幸的是,他们没有指定系统属性是什么,所以其他一些JVM可能只报告java.vm.name = Edgar。

BTW, by "installed on the system", I assume you mean "the current running JVM"? 顺便说一下,通过“安装在系统上”,我假设你的意思是“当前正在运行的JVM”?

There might be both 32 bit and 64 bit JVM's available on the system, and plenty of them. 系统上可能有32位和64位JVM,其中有很多。

If you already have dll's for each supported platform - consider making a small executable which links and run so you can test if the platform supports a given functionality. 如果您已经为每个支持的平台配备了dll - 请考虑制作一个链接和运行的小型可执行文件,以便您可以测试该平台是否支持给定的功能。 If the executable links and run, you can install the corresponding shared libraries. 如果可执行链接并运行,则可以安装相应的共享库。

If you have the path to the .exe you want to check, you can use this answer . 如果您有要检查的.exe的路径,则可以使用此答案 Basically it just looks at the headers in the .exe file and tells you whether or not it is 64 or 32 bit on Windows. 基本上它只是查看.exe文件中的标题,并告诉你它是否是Windows上的64位或32位。

The following code checks the machineType field in any windows executable to determine if it is 32 or 64 bit: 以下代码检查任何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;
  }
}

Note that the code has been compacted for brevity... 请注意,为简洁起见,代码已经过压缩...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM