检测 JDK 是否具有给定文件系统路径的模块系统的稳健且高性能的方法?

问题描述

我有一个启动 Java 程序的脚本,并允许用户通过环境变量指定要使用的 Java 安装路径

当目标 JDK 具有模块系统(JPMS 或“拼图”)时,我希望该脚本提供 Java 模块系统参数(特别是 --add-opens),并在提供时省略它们不(如果没有省略,启动将失败,因为 JDK 8 抱怨无法识别的参数)。现在它忽略了它们,这会导致在 JDK 9+ 上出现不良警告(是的,我也在研究解决根本原因)。

可以实现这一点。可能最健壮的方法是首先在检测模块系统的底层脚本中调用 Java 程序并将其结果发送到标准输出(或进程退出状态,也许);然后调用脚本可以检查该输出以了解底层 JDK 是否支持 JPMS。

我也可以解析 java -version,但我不确定该字符串的格式有什么保证。

我希望有一种方法 (1) 健壮,(2) 高性能——可能检查安装中是否存在特定文件,或者从调用脚本中扫描特定 JAR 文件,或其他。

有没有 JPMS 专家对此具有强大且高效的启发式方法

解决方法

java class file format 对于所有 Java 版本都是相同的,并且包含 version number。只需读取相关 .class 文件之一的标头字节即可。

例如,下面 PowerShell 命令输出的最后一行是版本号。

Get-Content -Path "Key.class" -TotalCount 8 -Encoding Byte

输出是

202
254
186
190
0
0
0
52

52 是版本号,表示文件 Key.class 是用 JDK 8 编译的。

,

Java 9 之后的每个版本都包含模块系统。

Java 9 及更高版本的每个 OpenJDK 派生实现,包括 Oracle 的商业 JDK 构建,都支持 --version 选项;早期版本仅支持 -version(单破折号)选项。因此,检查 9 及以后的快速而肮脏的方法是 if $JAVA_HOME/bin/java --version >&/dev/null; then ...