Just moved from Java 11 to Java 14.
The following code is now failing on a Linux machine:
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]));
with stacktrace
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)
What has changed in Java 14 that would cause this?
I ran the equivalent code on Windows using Java 14 and that did run okay. But I had retried with same code base on this Unix machine using both Java 11 and Java 14 and can confirm that Java 11 always works and Java 14 always fails.
I have found the issue, I came across these issues on the Openjdk Bugs Database
Provide a way for Runtime.exec to use posix_spawn on linux
and
Change the Process launch mechanism default on Linux to be posix_spawn
Essentially in Java 11 Linux uses vfork
to start processes but by Java 13 it now uses posix_spawn
.
posix_spawn
actually requires a program called jspawnhelper
that is located within jre/lib
. In my case this exists but it does not have execute permissions, this is because I use jlink
to build a jre that just has the system modules I need, but I create this on Windows (my main dev environment).
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 doesn't understand linux execute permissions, when I deploy my application I set execute permission on the executables that are in jre/bin
but didn't know there were any executables in jre/lib
. Changing the permissions on jspawnhelper to execute fixes the issue.
An alternative workaround is to add the following java option:
-Djdk.lang.Process.launchMechanism=vfork