Wie kann ich feststellen, ob die JVM, in der meine Anwendung läuft, 32-Bit oder 64-Bit ist? Welche Funktionen oder Eigenschaften kann ich verwenden, um dies innerhalb des Programms zu erkennen?
Antworten
Zu viele Anzeigen?Unter Linux können Sie ELF-Header-Informationen mit einem der beiden folgenden Befehle abrufen:
file {YOUR_JRE_LOCATION_HERE}/bin/java
o/p: ELF Ausführbare 64-Bit-LSB-Datei AMD x86-64, Version 1 (SYSV), für GNU/Linux 2.4.0, dynamisch gelinkt (verwendet gemeinsam genutzte Bibliotheken), für GNU/Linux 2.4.0, nicht gestrippt
oder
readelf -h {YOUR_JRE_LOCATION_HERE}/bin/java | grep 'Class'
o/p: Klasse: ELF 64
So löst JNA das Problem mit 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;
}
}
Sie können eine JNI-Bibliothek verwenden. Dies wird immer funktionieren und ist unabhängig von der laufenden JVM-Marke.
Java-Code:
package org.mytest;
public class NativeBinding
{
public static native int getRegisterWidth(); // returns 32 or 64
}
Und dies ist der 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;
}
4 Stimmen
Nur aus reiner Neugierde: Warum müssen Sie die natürliche Größe des Systems kennen? Details wie diese sind in Java abstrahiert, so dass Sie sie (zumindest theoretisch) nicht kennen müssen.
3 Stimmen
Damit kann ich den Speicherbedarf für Objekte aufgrund von Zeigern grob abschätzen. Neugier auch - schien, wie es sollte ein Weg sein, aber ich hatte noch nie davon gehört.
13 Stimmen
Eine weitere Situation, in der es wichtig ist, zwischen 32- und 64-Bit-JVMs zu unterscheiden, ist bei gemappten Dateien. Auf 32-Bit-Systemen können nur 2 GB abgebildet werden. Daher ist es wichtig, Dateisegmente entsprechend zuzuordnen und die Zuordnung aufzuheben, damit diese Grenze nicht überschritten wird, während die Grenze auf 64-Bit-JVMs viel, viel, viel höher ist.
0 Stimmen
@simonegianni wäre ein solches Mapping nicht der perfekte Test?
2 Stimmen
Es ist wirklich schön, wenn man den numerischen Algorithmus wählen kann, der auf dem betreffenden Rechner am schnellsten ist.
0 Stimmen
Beachten Sie auch, dass sowohl die Erkennungsmechanismen als auch die Objektgröße herstellerabhängig sind.
0 Stimmen
Beachten Sie, dass Java einige Tricks anwendet, damit "gewöhnliche Objektzeiger" auf 64-Bit-JVMs mit typischen Heap-Limits 32-Bit sind.
1 Stimmen
@PatrickNiedzielski Eine weitere Situation, in der die Unterscheidung zwischen 32- und 64-Bit-JVMs von größter Bedeutung ist, ist, wenn ein Java-Programm eine externe ausführbare Datei starten muss, für die beide Versionen existieren. Zum Beispiel beim Schreiben von Selenium-Tests, wo der richtige Browser-Treiber gestartet werden muss. Das gleiche gilt für die Unterscheidung des Betriebssystems. Ich bin sicher, man kann sich noch einige weitere Fälle vorstellen, in denen etwas, das eigentlich "abstrahiert" werden sollte, nicht existiert.