【发布时间】:2023-03-31 04:50:01
【问题描述】:
我需要在 Linux、Solaris 和 Windows 上对 JRE 1.6 中 os.arch 属性的所有可能值进行最新编译。 如果可能,请引用您的发现的来源。 我需要这些值来选择我的 JNLP 文件中的资源。基本上我需要根据 JRE 是 32 位还是 64 位来分配不同的 JVM 内存。 等待你的答复。 谢谢
【问题讨论】:
我需要在 Linux、Solaris 和 Windows 上对 JRE 1.6 中 os.arch 属性的所有可能值进行最新编译。 如果可能,请引用您的发现的来源。 我需要这些值来选择我的 JNLP 文件中的资源。基本上我需要根据 JRE 是 32 位还是 64 位来分配不同的 JVM 内存。 等待你的答复。 谢谢
【问题讨论】:
您可以在自己的 jdk 中查找此内容的最佳位置。
查看java.lang.System,您可以看到属性是使用initProperties 方法在initializeSystemClass 方法中初始化的,该方法依赖于使用JNI 的本机代码:
private static native Properties initProperties(Properties props);
/**
* Initialize the system class. Called after thread initialization.
*/
private static void initializeSystemClass() {
// VM might invoke JNU_NewStringPlatform() to set those encoding
// sensitive properties (user.home, user.name, boot.class.path, etc.)
// during "props" initialization, in which it may need access, via
// System.getProperty(), to the related system encoding property that
// have been initialized (put into "props") at early stage of the
// initialization. So make sure the "props" is available at the
// very beginning of the initialization and all system properties to
// be put into it directly.
props = new Properties();
initProperties(props); // initialized by the VM
...
...
}
如果您检查从 initProperties 调用的本机代码的来源,用于不同的平台,您可以看到 os.arch 系统属性的可能值。所以一步一步来:
首先查看System.c,可以看到从java.lang.System.initProperties 调用的JNI 方法。来自System.c
JNIEXPORT jobject JNICALL
Java_java_lang_System_initProperties(JNIEnv *env, jclass cla, jobject props)
{
char buf[128];
java_props_t *sprops = GetJavaProperties(env);
jmethodID putID = (*env)->GetMethodID(env,
(*env)->GetObjectClass(env, props),
"put",
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
if (sprops == NULL || putID == NULL ) return NULL;
PUTPROP(props, "java.specification.version",
JDK_MAJOR_VERSION "." JDK_MINOR_VERSION);
PUTPROP(props, "java.specification.name",
"Java Platform API Specification");
PUTPROP(props, "java.specification.vendor", "Sun Microsystems Inc.");
PUTPROP(props, "java.version", RELEASE);
PUTPROP(props, "java.vendor", VENDOR);
PUTPROP(props, "java.vendor.url", VENDOR_URL);
PUTPROP(props, "java.vendor.url.bug", VENDOR_URL_BUG);
...
/* os properties */
PUTPROP(props, "os.name", sprops->os_name);
PUTPROP(props, "os.version", sprops->os_version);
// HERE IS THE `os.arch` PROPERTY :)
PUTPROP(props, "os.arch", sprops->os_arch);
如您所见,os.arch 来自PUTPROP(props, "os.arch", sprops->os_arch);,sprops 是使用java_props_t *sprops = GetJavaProperties(env); 实现的。那么让我们看看GetJavaProperties(env),这个方法在java_props.h中定义为:
java_props_t *GetJavaProperties(JNIEnv *env);
而且实现似乎取决于操作系统。
所以终于找到了GetJavaProperties的具体实现;
在 Windows 中,此属性可以采用的可能值为 ia64、amd64、x86 或 unknown。你可以从java_props_md.c file看到:
#if _M_IA64
sprops.os_arch = "ia64";
#elif _M_AMD64
sprops.os_arch = "amd64";
#elif _X86_
sprops.os_arch = "x86";
#else
sprops.os_arch = "unknown";
#endif
对于 Solaris 似乎更复杂,因为本机代码中的属性值来自特定于 solaris 的 java_props_md.c 中定义的宏:
sprops.os_arch = ARCHPROPNAME;
而这个宏在Makefile 中定义为:
OTHER_CPPFLAGS += -DARCHPROPNAME='"$(ARCHPROP)"'
所以看起来这来自编译它的环境(对不起,我不是 C 专家,我只是猜测,但也许我可以指导你一点)。
在src/linux/native/ 的Linux 文件夹中没有java_props_md.c,所以我想在这种情况下采用与solaris 相同的源(我再次猜测......)。
注意:我使用 1.6 版本来获取这个值,但是新的值会在最新的 java 版本中添加,所以请检查您需要的版本。
希望对你有帮助,
【讨论】:
os.arch 的可能值,但似乎没有关于它的官方信息......所以我直接查看代码;不幸的是,这也没有提供我们正在寻找的信息。无论如何感谢:)的赏金。
您也可以编写如下代码来查找操作系统及其架构。
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang.SystemUtils;
public class PlatformDetection {
private String os;
private String arch;
public static String OS_WINDOWS = "windows";
public static String OS_OSX = "osx";
public static String OS_SOLARIS = "solaris";
public static String OS_LINUX = "linux";
public static String ARCH_PPC = "ppc";
public static String ARCH_X86_32 = "x86_32";
public static String ARCH_X86_64 = "x86_64";
public PlatformDetection() {
// resolve OS
if (SystemUtils.IS_OS_WINDOWS) {
this.os = OS_WINDOWS;
} else if (SystemUtils.IS_OS_MAC_OSX) {
this.os = OS_OSX;
} else if (SystemUtils.IS_OS_SOLARIS) {
this.os = OS_SOLARIS;
} else if (SystemUtils.IS_OS_LINUX) {
this.os = OS_LINUX;
} else {
throw new IllegalArgumentException("Unknown operating system " + SystemUtils.OS_NAME);
}
// resolve architecture
Map<String, String> archMap = new HashMap<String, String>();
archMap.put("x86", ARCH_X86_32);
archMap.put("i386", ARCH_X86_32);
archMap.put("i486", ARCH_X86_32);
archMap.put("i586", ARCH_X86_32);
archMap.put("i686", ARCH_X86_32);
archMap.put("x86_64", ARCH_X86_64);
archMap.put("amd64", ARCH_X86_64);
archMap.put("powerpc", ARCH_PPC);
this.arch = archMap.get(SystemUtils.OS_ARCH);
if (this.arch == null) {
throw new IllegalArgumentException("Unknown architecture " + SystemUtils.OS_ARCH);
}
}
public String getOs() {
return os;
}
public String getArch() {
return arch;
}
public void setArch(String arch) {
this.arch = arch;
}
public void setOs(String os) {
this.os = os;
}
public String toString() {
return os + "_" + arch;
}
}
参考以下链接
【讨论】:
os.arch 值(例如powerpc 与ppc),并且不清楚他们是否知道这些值可能会出现,或者它是否是迷信的编码。你也把其中一个复制粘贴在这里,我不知道它的版权状态是什么。
我在 2019 年遇到了同样的问题。尤其是在 arm 处理器方面。
试用后,树莓派 2 (ARMv7) 似乎只是简单地返回字符串arm。
树莓派 3 (ARMv8) 返回aarch64。
x86 64 位桌面和服务器返回 amd64。
希望这对某人有所帮助。
【讨论】: