我如何知道我的应用程序运行的JVM是32位还是64位?具体来说,我可以在程序中使用哪些函数或属性来检测这一点?
您可以检索标记此JVM位的系统属性:
System.getProperty("sun.arch.data.model");
可能的结果是:
"32"
"64"
"unknown"
如热点常见问题解答所述:
在编写Java代码时,如何区分32位和64位操作? 没有公共API允许你区分32位和64位操作。把64位看作是编写一次,随处运行的传统的另一个平台。然而,如果你想编写特定于平台的代码(真可耻),系统属性sun.arch.data.model的值是“32”、“64”或“unknown”。
在编写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的位。
-d32
-d64
$ 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即可。
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的缺失。
Client
64-Bit Server
Client/Server
64-Bit
如果您的系统上安装了多个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
或
readelf -h {YOUR_JRE_LOCATION_HERE}/bin/java | grep 'Class'
如果你正在使用JNA,你可以检查是com.sun.jna.Native.POINTER_SIZE == 4(32位)还是com.sun.jna.Native.POINTER_SIZE == 8(64位)。
com.sun.jna.Native.POINTER_SIZE == 4
com.sun.jna.Native.POINTER_SIZE == 8
在Windows 7下的“控制面板”下的“程序|程序和功能”64位版本的JRE &JDK都是用括号中的“64位”列出的(例如:“Java SE开发套件7 Update 65(64位)”),而对于32位的变量,括号中没有提到变量(例如,只有“Java SE Development Kit 8 Update 60”)。
获取当前运行程序的JVM版本
System.out.println(Runtime.class.getPackage().getImplementationVersion());
对于Windows,您可以检查Java主位置。如果包含(x86),则为32-bit,否则为64-bit:
Windows
Java
(x86)
32-bit
64-bit
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上的本机代码,因此无论如何,平台独立性都是不可能的。
如果使用JNA,可以执行Platform.is64Bit()。
Platform.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; }