12

刚刚从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 上运行了等效代码,并且运行良好。但是我已经在这台使用 Java 11 和 Java 14 的 unix 机器上重试了相同的代码库,并且可以确认Java 11 始终有效Java 14 始终失败

4

1 回答 1

12

我找到了问题,我在 Openjdk Bugs Database 上遇到了这些问题

为 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
于 2020-04-20T14:45:21.360 回答