如何判断运行应用程序的JVM是32位还是64位?具体来说,我可以使用哪些函数或属性在程序中检测到这一点?
如何判断运行应用程序的JVM是32位还是64位?具体来说,我可以使用哪些函数或属性在程序中检测到这一点?
对于某些版本的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中不再可用。
java -d32 -version
来验证你没有运行32位版本。两种方法都适用于Win7操作系统。 - Xonatronjava -d32 -version
或者java -d64 -version
时,会出现“未识别的选项”错误。 - ely您可以使用以下代码检索标记此JVM位数的系统属性:
System.getProperty("sun.arch.data.model");
"32"
– 32位JVM"64"
– 64位JVM"unknown"
– 未知的JVM这可能需要用到示例:如果您的Java代码依赖本机库,并且您需要确定在启动时加载32位或64位版本的库。编写Java代码时,如何区分32位和64位操作?
没有公共API允许您区分32位和64位操作。将64位视为遵循“一次编写,到处运行”传统的另一个平台。但是,如果您想编写特定于平台的代码(真是可耻),则系统属性sun.arch.data.model具有值“32”,“64”或“unknown”。
sun.*
开头的系统属性。换句话说,它不是可移植的。 - Pascal Thivent在您的控制台中键入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
。
我安装了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位)。显然,系统属性不仅仅是操作系统的架构。
os.arch
有很多可能的值,很难确定它是32位还是64位。请参阅 http://lopica.sourceforge.net/os.html。 - Emmanuel Bourg补充信息:
在一个正在运行的进程中,你可以使用以下方法(至少在一些最近的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 文件的位置。"
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如果使用JNA,您可以检查com.sun.jna.Native.POINTER_SIZE == 4
(32位)或com.sun.jna.Native.POINTER_SIZE == 8
(64位)。
如果您使用JNA,您可以这样做:Platform.is64Bit()
。
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;
}
}
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;
}