How can I tell if I'm running in 64-bit JVM or 32-bit JVM (from within a program)?

Viewed 711723

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?

13 Answers

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.

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.

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.

If you're using JNA, you can do thisPlatform.is64Bit().

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

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

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.

Related