如何在程序中判断我是否运行在64位JVM还是32位JVM?

607

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


4
只是出于好奇,你为什么需要知道系统的自然大小?像这样的细节在Java中被抽象化了,所以理论上你不需要知道它们。 - Patrick Niedzielski
3
它让我大致估计由指针引起的对象的内存需求。好奇心也是如此——似乎应该有一种方法,但我从未听说过。 - BobMcGee
90
在与Java本地接口交互时,这个“细节”并没有被抽象化。64位JVM无法加载32位DLL(反之亦然)。因此,对于使用JNI的任何人来说,这是非常重要的信息。遗憾的是,似乎没有一种可移植的方法来获取这些信息。一种方法是先尝试加载32位版本的DLL,如果失败了,则尝试64位版本等。这很丑陋! - Joonas Pulakka
12
另一个需要区分32位或64位JVM的情况是对于映射文件。在32位系统中,只能映射2GB,因此重要的是相应地映射和取消映射文件段,以避免超出此限制,而在64位JVM中,这个限制要高得多得多得多。 - Simone Gianni
2
能够选择在特定机器上运行最快的数值算法真是太好了。 - dfeuer
显示剩余5条评论
13个回答

760

对于某些版本的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中不再可用。


15
正是我要找的东西。并且,你可以运行java -d32 -version来验证你没有运行32位版本。两种方法都适用于Win7操作系统。 - Xonatron
36
我目前使用的是Windows 7操作系统,当我输入命令java -d32 -version或者java -d64 -version时,会出现“未识别的选项”错误。 - ely
44
不要使用 "-D64",因为它会完全做出不同的事情。它定义了一个名为 "64" 的系统属性,这绝对不是这里想要的。 - Jonathan Headland
10
-d32或-d64标志仅适用于Java 7或更高版本。 - darrenmc
显示剩余10条评论

337

您可以使用以下代码检索标记此JVM位数的系统属性

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

可能的结果如下:
  • "32" – 32位JVM
  • "64" – 64位JVM
  • "unknown" – 未知的JVM
HotSpot FAQ所述:

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

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

这可能需要用到示例:如果您的Java代码依赖本机库,并且您需要确定在启动时加载32位或64位版本的库。

23
我不会期望在IBM JVM中找到以sun.*开头的系统属性。换句话说,它不是可移植的。 - Pascal Thivent
8
怎么从命令行判断电脑是运行32位还是64位系统?只是好奇想知道。 - Xonatron
20
为什么被接受的答案与Sun相关?使用"os.arch"可以实现同样的功能而不必使用专有的sun包。 - arkon
8
@b1naryatr0phy,os.arch是报告操作系统还是JVM?我经常在64位工作站上运行32位JVM,用于开发目的。 - skiphoppy
8
此属性在IBM JVM上得到支持,但在GCJ上不支持。请参见https://dev59.com/cnRA5IYBdhLWcg3w1BqW。 - Emmanuel Bourg
显示剩余5条评论

201

在您的控制台中键入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)

注意第三行使用 Client 替代 64-Bit Server。关于 Client/Server 部分无关紧要,重要的是缺少了 64-Bit

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


但在HP NonStop OSS环境中,我无法获得64位或32位。 - vels4j
36
OP明确指出在程序内 - Tomáš Zato

37

我安装了32位的JVM并重试了一次,看起来以下代码确实是告诉你JVM的位数,而不是操作系统的架构:

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位)。显然,系统属性不仅仅是操作系统的架构。


是的。它提供了x86等内容。不完全相同,因为我不确定它是否会为在64位而非32位中运行的x86-64提供“x64”。 - BobMcGee
3
看起来确实是JVM位数的问题,@codaddict。 - bryantsai
21
这完全是错误的(我不知道为什么有六个人投赞成票)。"os.arch"被设计为返回JVM版本。自己测试一下吧,如果你真的依赖它来检测操作系统,愿上帝保佑你。 - arkon
6
os.arch 有很多可能的值,很难确定它是32位还是64位。请参阅 http://lopica.sourceforge.net/os.html。 - Emmanuel Bourg
2
这是一个为人类眼睛设计的字符串,没有严格定义有效值,依赖它不是一个好主意 - 写代码来检查实际功能才是明智之举。 - Thorbjørn Ravn Andersen
显示剩余2条评论

15

补充信息:

在一个正在运行的进程中,你可以使用以下方法(至少在一些最近的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。"os.arch"也可以起到同样的作用。

还支持其他情况:

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

但是请注意以下内容:

"注意 - 这个工具并没有得到官方支持,并且在未来的 JDK 版本中可能会有所更改。在 Windows 系统中,如果缺少 dbgent.dll,则需要安装“Windows 调试工具”才能使用这些工具。此外,PATH 环境变量应包含目标进程使用的 jvm.dll 或生成 Crash Dump 文件的位置。"


7
在Linux上,您可以使用以下两个命令之一获取ELF头信息:
file {YOUR_JRE_LOCATION_HERE}/bin/java

输出结果:

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

或者:

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

输出:

类别: ELF64


7

如果使用JNA,您可以检查com.sun.jna.Native.POINTER_SIZE == 4(32位)或com.sun.jna.Native.POINTER_SIZE == 8(64位)。


这很聪明,但访问指针大小比这里的其他解决方案慢得多(它需要一些时间来初始化)。 - BullyWiiPlaza

5

如果您使用JNA,您可以这样做:Platform.is64Bit()


1
这是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;
        }
}

0
你可以使用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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接