刚刚从 Java 11 迁移到 Java 14。
以下代码现在在 Linux 计算机上失败:
String linux_exe = System.getProperty("user.dir") + '/' + "fpcalc_arm32";
List<String> params = new ArrayList();
params.add(linux_exe);
params.add("-plain");
params.add("-length");
params.add(submittedSongLength);
params.add(file.getPath());
Process p = Runtime.getRuntime().exec(params.toArray(new String[1]));
带有堆栈跟踪
Cannot run program "/mnt/system/config/Apps/SongKong/songkong/fpcalc_arm32": error=0, Failed to exec spawn helper: pid: 13998, exit value: 127
java.io.IOException: Cannot run program "/mnt/system/config/Apps/SongKong/songkong/fpcalc_arm32": error=0, Failed to exec spawn helper: pid: 13998, exit value: 127
at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1128)
at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1071)
at java.base/java.lang.Runtime.exec(Runtime.java:590)
at java.base/java.lang.Runtime.exec(Runtime.java:449)
at com.jthink.songkong.analyse.acoustid.AcoustId.generateFingerprint(AcoustId.java:217)
at com.jthink.songkong.analyse.acoustid.AcoustId.createAcoustIdFingerprint(AcoustId.java:106)
Java 14 中发生了什么变化会导致这种情况?
我使用 Java 14 在 Windows 上运行了等效代码,并且运行正常。但我在这台 Unix 机器上使用 Java 11 和 Java 14 重试了相同的代码库,并且可以确认 Java 11 始终有效,而 Java 14 始终失败。
我发现了这个问题,我在 Openjdk Bugs 数据库上遇到了这些问题
为Runtime.exec提供在linux上使用posix_spawn的方法
和
将 Linux 上默认的进程启动机制更改为 posix_spawn
基本上在 Java 11 中,Linux 使用
vfork
来启动进程,但到了 Java 13,它现在使用 posix_spawn
。
posix_spawn
实际上需要一个名为 jspawnhelper
的程序,该程序位于 jre/lib
中。在我的例子中,它存在,但它没有执行权限,这是因为我使用 jlink
构建一个只有我需要的系统模块的 jre,但我在 Windows (我的主开发环境)上创建它。
call "C:\Program Files\AdoptOpenJDK\jdk-11.0.6.10-hotspot\bin\jlink" --module-path="C:\Code\jthink\SongKong\linux_jdk\jmods" --add-modules java.desktop,java.datatransfer,java.logging,java.management,java.naming,java.net.http,java.prefs,java.scripting,java.sql,jdk.management,jdk.unsupported,jdk.scripting.nashorn --output C:\code\jthink\songkong\linuxjre
Windows 不理解 Linux 执行权限,当我部署应用程序时,我对
jre/bin
中的可执行文件设置了执行权限,但不知道 jre/lib
中存在任何可执行文件。更改 jspawnhelper 的执行权限可以修复该问题。
另一种解决方法是添加以下 java 选项:
-Djdk.lang.Process.launchMechanism=vfork
同一错误消息的另一个相当奇特的原因可能是操作系统在程序运行时更新了 java 发行版,然后程序尝试执行外部进程。这发生在我们部署的服务器上,客户端更新了 java 发行版。解决方案就是重新启动服务。
我已重新启动 Jenkins 服务器。它解决了我的问题。 :)
就我而言, 我只是在 Jenkins 中更新了 Git 插件,然后重新启动 Jenkins 以应用更改。