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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/807263/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 19:41:57  来源:igfitidea点击:

How do I detect which kind of JRE is installed -- 32bit vs. 64bit

64-bit32-bitnsisjava

提问by user97629

During installation with an NSIS installer, I need to check which JRE (32bit vs 64bit) is installed on a system. I already know that I can check a system property "sun.arch.data.model", but this is Sun-specific. I'm wondering if there is a standard solution for this.

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

回答by Steve B.

On linux, my (java) vm reports java.vm.name=Java HotSpot(TM) 64-Bit Server VM. The javadocs for System declare that System.getProperty will always have a value for this but are silent on sun.arch.data.model.

在 linux 上,我的 (java) vm 报告 java.vm.name=Java HotSpot(TM) 64-Bit Server VM。System 的 javadocs 声明 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”?

回答by McDowell

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. Return values seem to be inconsistent.

“os”部分似乎有点用词不当,或者可能最初的设计者没想到 JVM 会运行在他们不适合的架构上。返回值似乎不一致

The NetBeans Installer team are tackling the issueof JVM vs OS architecture. Quote:

NetBeans 安装程序团队正在解决JVM 与操作系统架构的问题。引用:

x64 bit : Java and System

Tracked as the Issue 143434.

Currently we using x64 bit of JVM to determine if system (and thus Platform.getHardwareArch()) is 64-bit or not. This is definitely wrong since it is possible to run 32bit JVM on 64bit system. We should find a solution to check OS real 64-bitness in case of running on 32-bit JVM.

  • for Windows it can be done using WindowsRegistry.IsWow64Process()
  • for Linux - by checking 'uname -m/-p' == x86_64
  • for Solaris it can be done using e.g. '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..)
  • 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).

x64 位:Java 和系统

跟踪为问题 143434

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

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

来自不同 JVM 的示例属性都在 64 位 Ubuntu 8.0.4 上运行:

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 位 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

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

回答by Thorbj?rn Ravn Andersen

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. If the executable links and run, you can install the corresponding shared libraries.

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

回答by Peter Smith

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...

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

回答by Peter Smith

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

回答by Gene

I'm using NSIS and Launch4j to wrap a Java Desktop app. So I need not only to detect any JRE, but the one Launch4j will find with its search algorithm. The only approach that made sense is to run a short Java program within the NSIS installer. Here's the Java:

我正在使用 NSIS 和 Launch4j 来包装 Java 桌面应用程序。因此,我不仅需要检测任何 JRE,还要检测 Launch4j 将通过其搜索算法找到的 JRE。唯一有意义的方法是在 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);
                }
            }
        }
    }

Wrap this with Launch4J. Use the GUI header type but also set to true. Otherwise the error code will be lost. (I put all this in my Netbeans Ant build script.

用 Launch4J 包装它。使用 GUI 标头类型但也设置为 true。否则错误代码将丢失。(我把所有这些都放在了我的 Netbeans Ant 构建脚本中。

Here's the matching NSIS code that uses it:

这是使用它的匹配 NSIS 代码:

File ... ; unpack files including detectjvm.exe.
ClearErrors
ExecWait '"$INSTDIR\detectjvm.exe"' 
java -version
IfErrors DetectExecError IntCmp
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)
0 DetectError DetectError DoneDetect DetectExecError: StrCpy
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)
"exec error" DetectError: MessageBox MB_OK "Could not determine JVM architecture (##代码##). Assuming 32-bit." Goto NotX64 DoneDetect: IntCmp ##代码## 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.

这在从没有 SP 的 WinXP 到带有所有 SP(32 位和 64 位)的 Vista 和 Win7 的各种机器上都运行良好。

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.

希望这对某人有帮助。

回答by billsimons

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. Think of 64-bit as just another platform in the write once, run anywhere tradition. 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".

没有允许您区分 32 位和 64 位操作的公共 API。将 64 位视为一次编写、随处运行的传统平台。但是,如果您想编写特定于平台的代码(让您感到羞耻),则系统属性 sun.arch.data.model 具有值“32”、“64”或“未知”。

回答by 11101101b

If you have the path to the .exe you want to check, you can use this answer. 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 的路径,则可以使用此答案。基本上它只是查看 .exe 文件中的标题,并告诉您它在 Windows 上是 64 位还是 32 位。

回答by user6376564

##代码##

For a 64bit java version it'll print :

对于 64 位 java 版本,它将打印:

##代码##

For 32 bit it'll be just

对于 32 位,它只是

##代码##