我如何知道我的应用程序运行的JVM是32位还是64位?具体来说,我可以在程序中使用哪些函数或属性来检测这一点?


你检索系统属性,标记这个JVM的位:

System.getProperty("sun.arch.data.model");

可能的结果是:

“32” – 32 位 JVM “64” – 64 位 JVM “未知” – 未知 JVM

如热点常见问题解答所述:

在编写Java代码时,如何区分32位和64位操作? 没有公共API允许你区分32位和64位操作。把64位看作是编写一次,随处运行的传统的另一个平台。然而,如果你想编写特定于平台的代码,系统属性sun.arch.data.model的值是"32"、"64"或"unknown"。

需要这样做的一个例子是,如果您的Java代码依赖于本机库,并且需要确定在启动时是加载32位版本的库还是64位版本的库。


我安装了32位JVM,并再次重试,看起来以下确实告诉你JVM位,而不是OS arch:

System.getProperty("os.arch");
#
# on a 64-bit Linux box:
# "x86" when using 32-bit JVM
# "amd64" when using 64-bit JVM

这在SUN和IBM JVM(32和64位)上进行了测试。显然,系统属性不仅仅是操作系统拱门。


对于某些版本的Java,您可以使用标记-d32和-d64从命令行检查JVM的位。

$ java -help
...
    -d32          use a 32-bit data model if available
    -d64          use a 64-bit data model if available

要检查64位JVM,运行:

$ java -d64 -version

如果它不是一个64位JVM,你会得到这个:

Error: This Java instance does not support a 64-bit JVM.
Please install the desired version.

类似地,要检查32位JVM,运行:

$ java -d32 -version

如果它不是一个32位JVM,你会得到这个:

Error: This Java instance does not support a 32-bit JVM.
Please install the desired version.

这些标志是在Java 7中添加的,在Java 9中已弃用,在Java 10中被删除,并且在Java的现代版本中不再可用。


只需在控制台中输入java -version。

如果64位版本正在运行,你会得到这样的消息:

java version "1.6.0_18"
Java(TM) SE Runtime Environment (build 1.6.0_18-b07)
Java HotSpot(TM) 64-Bit Server VM (build 16.0-b13, mixed mode)

32位版本将显示类似的内容:

java version "1.6.0_41"
Java(TM) SE Runtime Environment (build 1.6.0_41-b02)
Java HotSpot(TM) Client VM (build 20.14-b01, mixed mode, sharing)

注意第三行是客户端,而不是64位服务器。客户端/服务器部分无关紧要,重要的是缺少64位。

如果您的系统上安装了多个Java版本,请导航到要检查的Java版本的/bin文件夹,并在那里键入Java -version。


补充信息:

在一个正在运行的进程中(至少在一些最新的Sun JDK5/6版本中):

$ /opt/java1.5/bin/jinfo -sysprops 14680 | grep sun.arch.data.model
Attaching to process ID 14680, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 1.5.0_16-b02
sun.arch.data.model = 32

其中14680是运行应用程序的jvm的PID。“操作系统。Arch”也可以。

还支持其他场景:

jinfo [ option ] pid
jinfo [ option ] executable core
jinfo [ option ] [server-id@]remote-hostname-or-IP 

然而,还要考虑到这一点:

注意-此实用程序不受支持,并且在JDK的未来版本中可能可用,也可能不可用。在dbgent.dll不存在的Windows系统中,需要安装“用于Windows的调试工具”才能使这些工具工作。此外,PATH环境变量应该包含目标进程使用的jvm.dll的位置或产生崩溃转储文件的位置。


在Linux上,您可以使用以下两个命令之一来获取ELF头信息:

file {YOUR_JRE_LOCATION_HERE}/bin/java

o / p: ELF 64位LSB可执行文件,AMD x86-64,版本1 (SYSV),适用于GNU/Linux 2.4.0,动态链接(使用共享库),适用于GNU/Linux 2.4.0,未剥离

or

readelf -h {YOUR_JRE_LOCATION_HERE}/bin/java | grep 'Class'

o / p: 类 : ELF64


如果您使用的是JNA,您可以检查com.sun.jna.Native. net是否为JNA。POINTER_SIZE == 4(32位)或com.sun.jna.Native。指针大小== 8(64位)。


在Windows 7的“控制面板”下的“程序|程序和功能”中,64位的JRE和JDK变体被列出,括号中有“64位”(例如:“Java SE Development Kit 7 Update 65(64位)”),而对于32位的变体,括号中没有提到该变体(例如,只是“Java SE Development Kit 8 Update 60”)。


获取当前运行程序的JVM版本

System.out.println(Runtime.class.getPackage().getImplementationVersion());

对于Windows,您可以检查Java主位置。如果包含(x86),则为32位,否则为64位:

public static boolean is32Bit()
{
    val javaHome = System.getProperty("java.home");
    return javaHome.contains("(x86)");
}

public static boolean is64Bit()
{
    return !is32Bit();
}

示例路径:

C:\Program Files (x86)\Java\jdk1.8.0_181\bin\java.exe # 32-bit
C:\Program Files\Java\jdk-10.0.2\bin\java.exe # 64-bit

为什么只关心Windows解决方案呢?

如果你需要知道你在哪个位版本上运行,你可能会摆弄Windows上的本机代码,所以平台独立性是不可能的。


如果你正在使用JNA,你可以使用thisPlatform.is64Bit()。


这是JNA用Platform.is64Bit() (https://github.com/java-native-access/jna/blob/master/src/com/sun/jna/Platform.java)解决这个问题的方法。

 public static final boolean is64Bit() {
        String model = System.getProperty("sun.arch.data.model",
                                          System.getProperty("com.ibm.vm.bitmode"));
        if (model != null) {
            return "64".equals(model);
        }
        if ("x86-64".equals(ARCH)
            || "ia64".equals(ARCH)
            || "ppc64".equals(ARCH) || "ppc64le".equals(ARCH)
            || "sparcv9".equals(ARCH)
            || "mips64".equals(ARCH) || "mips64el".equals(ARCH)
            || "amd64".equals(ARCH)
            || "aarch64".equals(ARCH)) {
            return true;
        }
        return Native.POINTER_SIZE == 8;
}

ARCH = getCanonicalArchitecture(System.getProperty("os.arch"), osType);

static String getCanonicalArchitecture(String arch, int platform) {
        arch = arch.toLowerCase().trim();
        if ("powerpc".equals(arch)) {
            arch = "ppc";
        }
        else if ("powerpc64".equals(arch)) {
            arch = "ppc64";
        }
        else if ("i386".equals(arch) || "i686".equals(arch)) {
            arch = "x86";
        }
        else if ("x86_64".equals(arch) || "amd64".equals(arch)) {
            arch = "x86-64";
        }
        // Work around OpenJDK mis-reporting os.arch
        // https://bugs.openjdk.java.net/browse/JDK-8073139
        if ("ppc64".equals(arch) && "little".equals(System.getProperty("sun.cpu.endian"))) {
            arch = "ppc64le";
        }
        // Map arm to armel if the binary is running as softfloat build
        if("arm".equals(arch) && platform == Platform.LINUX && isSoftFloat()) {
            arch = "armel";
        }

        return arch;
    }

static {
        String osName = System.getProperty("os.name");
        if (osName.startsWith("Linux")) {
            if ("dalvik".equals(System.getProperty("java.vm.name").toLowerCase())) {
                osType = ANDROID;
                // Native libraries on android must be bundled with the APK
                System.setProperty("jna.nounpack", "true");
            }
            else {
                osType = LINUX;
            }
        }
        else if (osName.startsWith("AIX")) {
            osType = AIX;
        }
        else if (osName.startsWith("Mac") || osName.startsWith("Darwin")) {
            osType = MAC;
        }
        else if (osName.startsWith("Windows CE")) {
            osType = WINDOWSCE;
        }
        else if (osName.startsWith("Windows")) {
            osType = WINDOWS;
        }
        else if (osName.startsWith("Solaris") || osName.startsWith("SunOS")) {
            osType = SOLARIS;
        }
        else if (osName.startsWith("FreeBSD")) {
            osType = FREEBSD;
        }
        else if (osName.startsWith("OpenBSD")) {
            osType = OPENBSD;
        }
        else if (osName.equalsIgnoreCase("gnu")) {
            osType = GNU;
        }
        else if (osName.equalsIgnoreCase("gnu/kfreebsd")) {
            osType = KFREEBSD;
        }
        else if (osName.equalsIgnoreCase("netbsd")) {
            osType = NETBSD;
        }
        else {
            osType = UNSPECIFIED;
        }
}

您可以使用JNI库。这将始终工作,并且独立于运行的JVM品牌。

Java代码:

package org.mytest;

public class NativeBinding
{
    public static native int getRegisterWidth(); // returns 32 or 64
}

这是C代码:

#include <jni.h>

// will return register width (32 or 64)
extern "C" JNIEXPORT jint JNICALL
Java_org_mytest_NativeBinding_getRegisterWidth(JNIEnv*, jclass)
{
    return sizeof(void*) * 8;
}