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

发布于 2024-08-17 10:04:27 字数 66 浏览 2 评论 0原文

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

How can I tell if the JVM in which my application runs is 32 bit or 64-bit? Specifically, what functions or properties I can used to detect this within the program?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

ヤ经典坏疍 2024-08-24 10:04:28

如果你使用 JNA,你可以这样做

Platform.is64Bit()

If you're using JNA, you can do this

Platform.is64Bit()
不再让梦枯萎 2024-08-24 10:04:28

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

This is the way JNA solves this with 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;
        }
}
三生一梦 2024-08-24 10:04:28

我相信以下内容,它使用 Foreign Function & Java 22 中添加的 Memory API 应该是一种可靠的方法。

import java.lang.foreign.ValueLayout;

public final class Platform {

  public static boolean is64Bit() {
    return ValueLayout.ADDRESS.byteSize() == 8;
  }

  public static boolean is32Bit() {
    return ValueLayout.ADDRESS.byteSize() == 4;
  }

  private Platform() {}
}

ValueLayout.ADDRESS

地址布局常量,其大小与机器地址相同 (size_t),字节对齐设置为 sizeof(size_t),字节顺序设置为 <代码>ByteOrder.nativeOrder().

I believe the following, which uses the Foreign Function & Memory API added in Java 22, should be a reliable approach.

import java.lang.foreign.ValueLayout;

public final class Platform {

  public static boolean is64Bit() {
    return ValueLayout.ADDRESS.byteSize() == 8;
  }

  public static boolean is32Bit() {
    return ValueLayout.ADDRESS.byteSize() == 4;
  }

  private Platform() {}
}

Documentation of ValueLayout.ADDRESS:

An address layout constant whose size is the same as that of a machine address (size_t), byte alignment set to sizeof(size_t), byte order set to ByteOrder.nativeOrder().

ゝ偶尔ゞ 2024-08-24 10:04:28

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

You can use a JNI library. This will always work and is independent of the running JVM brand.

Java code:

package org.mytest;

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

And this is the C code:

#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;
}
成熟稳重的好男人 2024-08-24 10:04:28

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

Under Windows 7 in the "Control Panel" under "Programs | Programs and Features" the 64-bit variants of JRE & JDK are listed with "64-bit" in parentheses (e.g. "Java SE Development Kit 7 Update 65 (64-Bit)"), while for the 32-bit variants the variant is not mentioned in parentheses (e.g. just "Java SE Development Kit 8 Update 60").

仅冇旳回忆 2024-08-24 10:04:28

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

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

To get the version of JVM currently running the program

System.out.println(Runtime.class.getPackage().getImplementationVersion());
来世叙缘 2024-08-24 10:04:28

对于 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 上摆弄本机代码,因此平台无关性无论如何都是不可能的。

For Windows, you can check the Java home location. If it contains (x86) it is 32-bit otherwise 64-bit:

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

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

Example paths:

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

Why care about a Windows only solution?

If you need to know which bit version you're running on, you're likely fiddling around with native code on Windows so platform-independence is out of the window anyway.

何必那么矫情 2024-08-24 10:04:27

对于某些版本的 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 中已删除,并且在现代版本中不再可用爪哇。

For certain versions of Java, you can check the bitness of the JVM from the command line with the flags -d32 and -d64.

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

To check for a 64-bit JVM, run:

$ java -d64 -version

If it's not a 64-bit JVM, you'll get this:

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

Similarly, to check for a 32-bit JVM, run:

$ java -d32 -version

If it's not a 32-bit JVM, you'll get this:

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

These flags were added in Java 7, deprecated in Java 9, removed in Java 10, and no longer available on modern versions of Java.

十秒萌定你 2024-08-24 10:04:27

您检索标记此 JVM 位数的 系统属性

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

可能的结果是:

  • "32" – 32 位 JVM
  • "64" – 64 位 JVM
  • "unknown" – 未知 JVM

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

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

没有公共 API 可以让您区分 32 位和 64 位操作。将 64 位视为“一次编写、随处运行”传统中的另一个平台。但是,如果您想编写特定于平台的代码(真丢脸),系统属性 sun.arch.data.model 的值为“32”、“64”或“未知”。

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

You retrieve the system property that marks the bitness of this JVM with:

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

Possible results are:

  • "32" – 32-bit JVM
  • "64" – 64-bit JVM
  • "unknown" – Unknown JVM

As described in the HotSpot FAQ:

When writing Java code, how do I distinguish between 32 and 64-bit operation?

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

An example where this could be necessary is if your Java code depends on native libraries, and you need to determine whether to load the 32- or 64-bit version of the libraries on startup.

沉鱼一梦 2024-08-24 10:04:27

只需在控制台中输入 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第三行。 客户端/服务器部分是无关紧要的,重要的是缺少64位

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

Just type java -version in your console.

If a 64 bit version is running, you'll get a message like:

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)

A 32 bit version will show something similar to:

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)

Note Client instead of 64-Bit Server in the third line. The Client/Server part is irrelevant, it's the absence of the 64-Bit that matters.

If multiple Java versions are installed on your system, navigate to the /bin folder of the Java version you want to check, and type java -version there.

辞慾 2024-08-24 10:04:27

我安装了 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 位)进行测试的。显然,系统属性不仅仅是操作系统架构。

I installed 32-bit JVM and retried it again, looks like the following does tell you JVM bitness, not OS arch:

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

This was tested against both SUN and IBM JVM (32 and 64-bit). Clearly, the system property is not just the operating system arch.

那一片橙海, 2024-08-24 10:04:27

补充信息:

正在运行的进程上,您可以使用(至少对于某些最新的 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 

但是,还要考虑此注释:

注意 - 此实用程序不受支持,并且在不存在 dbgent.dll 的 Windows 系统中可能可用,也可能不可用,需要安装“Windows 调试工具”才能使这些工具正常工作。变量应包含目标进程使用的 jvm.dll 的位置或生成故障转储文件的位置。”

Complementary info:

On a running process you may use (at least with some recent Sun JDK5/6 versions):

$ /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

where 14680 is PID of jvm running the application. "os.arch" works too.

Also other scenarios are supported:

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

However consider also this note:

"NOTE - This utility is unsupported and may or may not be available in future versions of the JDK. In Windows Systems where dbgent.dll is not present, 'Debugging Tools for Windows' needs to be installed to have these tools working. Also the PATH environment variable should contain the location of jvm.dll used by the target process or the location from which the Crash Dump file was produced."

原野 2024-08-24 10:04:27

如果您使用 JNA,则可以检查是否 com.sun.jna.Native.POINTER_SIZE == 4(32 位)或 com.sun.jna.Native.POINTER_SIZE == 8< /代码>(64 位)。

If you are using JNA, you can check whether com.sun.jna.Native.POINTER_SIZE == 4 (32 bit) or com.sun.jna.Native.POINTER_SIZE == 8 (64 bit).

韵柒 2024-08-24 10:04:27

在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,不剥离

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

o/p:
班级:ELF64

On Linux, you can get ELF header information by using either of the following two commands:

file {YOUR_JRE_LOCATION_HERE}/bin/java

o/p:
ELF 64-bit LSB executable, AMD x86-64, version 1 (SYSV), for GNU/Linux 2.4.0, dynamically linked (uses shared libs), for GNU/Linux 2.4.0, not stripped

or

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

o/p:
Class: ELF64

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文