1. Overview
Although Java is platform-independent, there are times when we have to use native libraries. In those cases, we might need to identify the underlying platform and load the appropriate native libraries on startup.
In this tutorial, we’ll learn different ways to check if a Java program is running on a 64-bit or 32-bit JVM.
First, we’ll show how to achieve this using the System class.
Then, we’ll see how to use the Java Native Access (JNA) API to check the bitness of the JVM. JNA is a community-developed library that enables all native access.
2. Using the sun.arch.data.model System Property
The System class in Java provides access to externally defined properties and environment variables. It maintains a Properties object that describes the configuration of the current working environment.
We can use the “sun.arch.data.model” system property to identify JVM bitness:
System.getProperty("sun.arch.data.model");
It contains “32” or “64” to indicate a 32-bit or 64-bit JVM, respectively. Although this approach is easy to use, It returns “unknown” if the property is not present. Hence, it will work only with Oracle Java versions.
Let’s see the code:
public class JVMBitVersion {
public String getUsingSystemClass() {
return System.getProperty("sun.arch.data.model") + "-bit";
}
//... other methods
}
Let’s check this approach through a unit test:
@Test
public void whenUsingSystemClass_thenOutputIsAsExpected() {
if ("64".equals(System.getProperty("sun.arch.data.model"))) {
assertEquals("64-bit", jvmVersion.getUsingSystemClass());
} else if ("32".equals(System.getProperty("sun.arch.data.model"))) {
assertEquals("32-bit", jvmVersion.getUsingSystemClass());
}
}
3. Using the JNA API
JNA (Java Native Access) supports various platforms such as macOS, Microsoft Windows, Solaris, GNU, and Linux.
It uses native functions to load a library by name and retrieve a pointer to a function within that library.
3.1. Native Class
We can use POINTER_SIZE from the Native class. This constant specifies the size (in bytes) of a native pointer on the current platform.
A value of 4 indicates a 32-bit native pointer, while a value of 8 indicates a 64-bit native pointer:
if (com.sun.jna.Native.POINTER_SIZE == 4) {
// 32-bit
} else if (com.sun.jna.Native.POINTER_SIZE == 8) {
// 64-bit
}
3.2. Platform Class
Alternatively, we can use the Platform class, which provides simplified platform information.
It contains the is64Bit() method that detects whether the JVM is 64-bit or not.
Let see how it identifies the bitness:
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;
}
Here, the ARCH constant is derived from the “os.arch” property via the System class. It is used to get operating system architecture:
ARCH = getCanonicalArchitecture(System.getProperty("os.arch"), osType);
This approach works for different operating systems and also with different JDK vendors. Hence, it is more reliable than the “sun.arch.data.model” system property.
4. Conclusion
In this tutorial, we learned how to check the JVM bit version. We also observed how JNA simplified the solution for us on different platforms.
As always, the complete code is available over on GitHub.