Repository navigation
OpenGL/3D sketches crash with UnsatisfiedLinkError on Linux when the bundled sketch JDK cannot fork+exec #1537
Description
Most appropriate sub-area of Processing 4?
OpenGL
Processing version
4.5.5
Operating system
EndeavourOS x86_64 Linux 7.0.5
Bug description
Every 3D/OpenGL sketch (P3D, P2D, Lights, OBJ-loading sketches, or anything that using JOGL) fails at launch:
Warning: Caught Exception while retrieving executable temp base directory:
java.io.IOException: Could not determine a temporary executable directory
at com.jogamp.common.util.IOUtil.getTempDir(IOUtil.java:1401)
at com.jogamp.common.util.cache.TempFileCache.<clinit>(TempFileCache.java:84)
at com.jogamp.common.os.Platform$1.run(Platform.java:313)
...
java.lang.UnsatisfiedLinkError: 'boolean jogamp.common.jvm.JVMUtil.initialize(java.nio.ByteBuffer)'
at jogamp.common.jvm.JVMUtil.initialize(Native Method)
at com.jogamp.common.os.Platform.<clinit>(Platform.java:290)
at com.jogamp.opengl.GLProfile.<clinit>(GLProfile.java:151)
at processing.opengl.PSurfaceJOGL.initGL(PSurfaceJOGL.java:204)
...
A library used by this sketch relies on native code that is not available.
2D (Java2D) sketches run fine.
Findings using Ai Agents
JOGL's IOUtil.testDirExec() writes a tiny test script into a temp directory, sets +x, and actually execve()s it to verify the temp dir allows execution. If that exec fails, JOGL's native-lib cache (TempFileCache) never starts, and subsequent JVMUtil.initialize (a native method) fails with UnsatisfiedLinkError.
The bundled sketch JDK at resources/jdk (Temurin 17.0.19) cannot fork+exec anything even /bin/true as a child process, while the system's own JDK on the same machine/user succeeds.
This was confirmed by running the exact same Java program on both JDKs (Build-in and System):
# bundled Temurin 17 (Build-In):
new ProcessBuilder("/bin/true").start()
→ IOException: Cannot run program "/bin/true": error=13, Permission denied
# system OpenJDK 21 (System):
new ProcessBuilder("/bin/true").start()
→ OK exit 0
error=13 is EACCES. This is a per-process exec denial affecting only the bundled binary (same uid, same caps, no seccomp, no AppArmor/SELinux). The exact mechanism applying the denial is unconfirmed (likely a Landlock restriction from the environment, not from the JVM itself, perhaps the bundled libjvm does not reference landlock symbols).
Why Platform.getJavaHome() can't recover
processing/app/Platform.getJavaHome() either returns resources/jdk (the broken bundle) or falls back to java.home (the IDE's own runtime at lib/runtime/). On the jpackage-based Linux install the IDE runtime has no bin/java (the launcher loads the JVM in-process via libjli.so, so a standalone java binary is not shipped in that tree). The fallback is therefore dead on Linux: removing resources/jdk gives a "file not found" error instead of working.
No preference or environment variable is read for the sketch JDK path — confirmed by decompiling Platform, Runner, and JavaBuild.
Affected file(s)
processing/app/Platform.java—getJavaHome()andgetJavaPath()
Suggested fix direction
Before returning the bundled resources/jdk from getJavaHome(), validate it can launch a child process (one-shot Runtime.exec("/bin/true")). When it fails:
- Honor
JAVA_HOME/JDK_HOMEenv vars or aruntime.java.pathpreference before the bundled JDK, so users can override a broken bundle. - On Linux, probe a system JDK (
/usr/lib/jvm/default-runtime,update-alternatives --list java,archlinux-java) as the fallback before giving up. - Report a clear message when no working JDK is found, instead of letting the crash surface as an opaque
UnsatisfiedLinkErrorfrom JOGL.
Verified workaround
sudo mv resources/jdk resources/jdk.broken
sudo ln -s /usr/lib/jvm/{any installed JDK} resources/jdkAfter this, JOGL initializes cleanly (GLProfile init OK, GL 4.6 hardware detected) and all 3D sketches render.
Steps to reproduce this
-
Run any 3D/OpenGL sketch (P3D, P2D,
Lights, OBJ-loading sketches, or anything that using JOGL -
Crash
snippet
Using OnOff sketch template
/**
* On/Off.
*
* Uses the default lights to show a simple box. The lights() function
* is used to turn on the default lighting. Click the mouse to turn the
* lights off.
*/
float spin = 0.0;
void setup() {
size(640, 360, P3D);
noStroke();
}
void draw() {
background(51);
if (!mousePressed) {
lights();
}
spin += 0.01;
pushMatrix();
translate(width/2, height/2, 0);
rotateX(PI/9);
rotateY(PI/5 + spin);
box(150);
popMatrix();
}```
### Additional context
## Environment
- Arch Linux, kernel 7.0.5-arch1-1-g14
- Processing 4.5.5, bundled sketch JDK Temurin 17.0.19+10
- System JDK: OpenJDK 21.0.11 at `/usr/lib/jvm/java-21-openjdk`
- `/tmp`: `tmpfs (rw,noatime)` — not `noexec`
### Would you like to work on the issue?
Yes, I’d like to help with this
Activity
catilac commentedon Jul 7, 2026
@ZanDev32 thanks for reporting this, and offering to help fix it. I've gone ahead and assigned it to you!
fix: preserve exec permissions on jspawnhelper in bundled JDK ([proce…
jvprat commentedon Sep 20, 2026
I'm facing the same issue on the Raspberry PI OS (trixie).
I tried both Processing 4.5.6 and 4.5.7 RC1, as #1571 sounded like it could make a difference, but it didn't.
In the end I tried the portable zip releases (processing-*-linux-aarch64-portable.zip), and it worked correctly for both 4.5.6 and 4.5.7 RC1, so it seems the issue is in the .deb packaging.
catilac commentedon Sep 20, 2026
gvlx commentedon Oct 30, 2026
Workaround works on
.deb installation : processing-4.5.7-linux-x64.deb from installation
/opt/processing/lib/app/resources/jdkusing/usr/lib/jvm/temurin-25-jdk-amd64on LMDE 7 Gigi Debian 6.12.113-1. (without native file dialogs Save dialog unusable #1526 ).flatpak installation: processing-4.5.7-linux-x64.flatpak from installation
/var/lib/flatpak/app/org.processing.pde/x86_64/master/active/files/lib/app/resources/jdkusing a copy of/usr/lib/jvm/temurin-25-jdk-amd64(ln -sdoes not work) on LMDE 7 Gigi Debian 6.12.113-1. (native dialogs work)Note: the files in the folders
jdkandlaunch4jdiffer significantly in size in the .deb and .flatpak versions.example: