【问题标题】:All possible values os.arch in 32bit JRE and in 64bit Jre32 位 JRE 和 64 位 Jre 中所有可能的 .arch 值
【发布时间】:2023-03-31 04:50:01
【问题描述】:

我需要在 Linux、Solaris 和 Windows 上对 JRE 1.6 中 os.arch 属性的所有可能值进行最新编译。 如果可能,请引用您的发现的来源。 我需要这些值来选择我的 JNLP 文件中的资源。基本上我需要根据 JRE 是 32 位还是 64 位来分配不同的 JVM 内存。 等待你的答复。 谢谢

【问题讨论】:

    标签: java jnlp


    【解决方案1】:

    您可以在自己的 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 中,此属性可以采用的可能值为 ia64amd64x86unknown。你可以从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 版本中添加,所以请检查您需要的版本。

    希望对你有帮助,

    【讨论】:

    • 虽然这不是一个完整的解决方案,但我给了它赏金,因为您努力寻找规范值。注意:由于历史原因,在 jdk9 之前的 Java 中,Solaris 文件夹包含大部分通用 Unix 内容,所以是的,该代码适用于 Linux。不幸的是,如果值来自环境,因为这意味着它的值是open-ended。我希望有一个整洁、规范的可能值表,而不需要迷信地包含许多架构同义词,但也许这是不可能的。
    • @Boann 感谢您对 solaris 和 linux 的确认。起初我查看文档以查看os.arch 的可能值,但似乎没有关于它的官方信息......所以我直接查看代码;不幸的是,这也没有提供我们正在寻找的信息。无论如何感谢:)的赏金。
    【解决方案2】:

    您也可以编写如下代码来查找操作系统及其架构。

    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;
        }
    }
    

    参考以下链接

    1. https://github.com/trustin/os-maven-plugin/blob/master/src/main/java/kr/motd/maven/os/Detector.java

    2. https://github.com/rachelxqy/EligibilityCriteriaModeling/blob/57001f6d86084f074f4ca6aaff157e93ef6abf95/src/main/java/edu/mayo/bmi/medtagger/ml/util/PlatformDetection.java

    【讨论】:

    • 我没有给这个答案赏金,因为不清楚链接的可靠性。他们为某些相同的架构检测到不同的os.arch 值(例如powerpcppc),并且不清楚他们是否知道这些值可能会出现,或者它是否是迷信的编码。你也把其中一个复制粘贴在这里,我不知道它的版权状态是什么。
    【解决方案3】:

    我在 2019 年遇到了同样的问题。尤其是在 arm 处理器方面。

    试用后,树莓派 2 (ARMv7) 似乎只是简单地返回字符串arm

    树莓派 3 (ARMv8) 返回aarch64

    x86 64 位桌面和服务器返回 amd64

    希望这对某人有所帮助。

    【讨论】:

      猜你喜欢
      • 2013-06-21
      • 2018-03-04
      • 2013-11-24
      • 2011-02-26
      • 1970-01-01
      • 1970-01-01
      • 2012-08-19
      • 1970-01-01
      • 2011-04-24
      相关资源
      最近更新 更多