问题描述
我有一个启动 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 ...
。