Big Sur 上的 Java 8 将 os.name 报告为“Mac OS X”,将 os.version 报告为“10.16”

时间:2021-02-03 11:30:58

标签: java macos-big-sur

是我的设置还是其他人有这个问题?

使用安装在以下位置的 AdoptOpenJDK 1.8.0_275:

/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre

System.getProperties() 的 API 文档未指定任何详细信息。

2 个答案:

答案 0 :(得分:4)

可以确认这种情况在adaptopenjdk14 以及用于j16 的openjdk 早期访问版本上仍然发生。

如果你愿意,你可以提交一个错误,但我敢打赌它会被拒绝。在这一点上,名称 Mac OS X 与其说是“操作系统的名称”,还不如说是“标识基于 Unix 的 mac 操作系统的全球公认的关键字”,我的意思是全局字面意思(例如,“围绕地球”,而不是“跨越您的源基础/虚拟机”)。改变它只会不必要地破坏东西。这同样适用于 10.16 版,但在较小程度上适用于 10.16 版:点之前的内容与其说是“这是操作系统识别自身的方式”,还不如说是“全球商定的 Mac OS 版本控制方案,确定了一个广泛且定义不明确的版本”能力集'。

big sur 和 catalina 之间的过渡没有有意义的区别,除了苹果做出了营销决策这一事实。如果您想指出一个操作系统转换可能保证完全模糊的选择将其视为“重大更改”,那么它肯定是 to catalina 的转换,因为它做出了迄今为止最大的更改(包括在最后一批版本中完全取消对 32 位的支持。

这给您带来了以下挑战:好的,太好了,我可以使用 System.getProperty("os.name") 来获得全球一致同意的关键字,这意味着类 Unix 的 Mac OS,以及 os.version 的字符串,我可以分成几位找出一些模糊的功能,但是如果我需要操作系统的实际名称来例如显示给用户?

那么你有三个主要选择:

  1. 最简单的就是编写映射代码。承认 os.nameos.version 为您提供(可以说是)有用的意图而不是太多的官方名称,因此,请编写一些映射。这些会将名称/版本对映射到呈现字符串,回退到仅打印名称字符串和版本字符串,逐字连接。您可以在此表中添加映射:Mac OS X/10.16Mac OS Big Sur

  2. 困难的方法:确定您使用的是 mac(现在更容易;os.name 返回 Mac OS X,或者只是检查是否存在:Files.isExecutable(Paths.get("/usr/bin/sw_vers"))),然后用ProcessBuilder执行/usr/bin/sw_vers,把所有的输出取出来变成一个大字符串,然后解析。它的输出看起来像:

ProductName:    macOS
ProductVersion: 11.1
BuildVersion:   20C69

至关重要的是,它甚至不包含单词 Big Sur,但确实给了您 11.1。我不知道如何运行实际为您提供 Big Sur 的命令行工具。也许 system_profiler,但请注意,这需要几分钟才能运行,我真的怀疑您是否想运行它。

注意:你也可以运行 .command("/usr/bin/sw_vers", "-productVersion") ,它只给你 11.1,这可能更容易解析。 -productName 也有效,只给你 macOS

  1. 如果您需要此信息来扫描操作系统功能,请停止这样做。它不适用于浏览器,也不是操作系统版本的好计划。您正在扫描什么功能?想象一下,例如,如果它是“我可以运行 /usr/bin/sw_vers 来解决问题吗”,作为一个假设的例子。正确的策略是检查 os.name/os.version,断定该命令必须存在,然后运行它,如果它不存在,将导致灾难性的失败。正确的做法是检查 /usr/bin/sw_vers 是否存在,然后执行它,在其他情况下回退到一些基于非 mac 的解决方案(可能是 /usr/bin/uname)。扫描功能,不要扫描操作系统/版本。

答案 1 :(得分:0)

调用原生工具sw_vers的Java代码

关于 Answer by rzwitserloot 中的选项 # 2,这里是一个完整的代码示例,用于从 Java 运行一个命令行工具 sw_vers,它描述了主机上运行的 macOS 软件的版本。

如果在命令行(控制台)上,例如在 Terminal.app 中,您运行:

sw_vers

...在 Intel Mac 上的 Big Sur 中,我们得到:

ProductName:    macOS
ProductVersion: 11.2
BuildVersion:   20D64

我们只需要中间件。所以运行:

sw_vers -productVersion

...仅显示 11.2,我们为您的目的所需的价值。

这是完整的示例应用程序,其中包含将此字符串返回到 Java 中的方法。

ProcessBuilder 类创建操作系统进程。每个新进程都由 Process 类表示。

我们使用 try-with-resources 语法自动关闭 InputStreamScanner 对象。

一旦你拿到了 11.2 字符串,在 FULL STOP 处分开,拉第一个数字 11,你就知道你在 Big Sur 上跑步了。

package org.example;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;

/**
 * Example code showing how to get current version of macOS from Java
 * by running a native command-line tool `sw_vers`.
 */
public class App
{
    public static void main ( String[] args )
    {
        App app = new App();
        app.demo();
    }

    private void demo ( )
    {
        String version = this.getMacOsVersionNumber();
        System.out.println( "version = " + version );
    }

    public String getMacOsVersionNumber ( )
    {
        String result = "";
        List < String > command = List.of( "sw_vers" , " -productVersion" );
        try (
                InputStream inputStream = new ProcessBuilder( command ).start().getInputStream() ;
                Scanner s = new Scanner( inputStream ).useDelimiter( "\\A" ) ;
        )
        {
            result = s.hasNext() ? s.next() : "";
        }
        catch ( IOException e )
        {
            e.printStackTrace();
        }
        return Objects.requireNonNull( result );
    }
}