java-native-access/jna · critical · java.io.IOException
JNA temporary directory 'jnatmp' is not writable
Error message
JNA temporary directory 'jnatmp' is not writable
What it means
JNA stages its native library into a temporary directory and requires write access there to extract the .so/.dll/.jnilib file. After confirming the directory exists, it checks canWrite(); if the process lacks write permission it throws this IOException. Without write access JNA cannot materialize the native library, so native calls cannot proceed.
Source
Thrown at src/com/sun/jna/Native.java:1425
}
jnatmp = new File(xdgCacheFile, "JNA/temp");
} else {
// Loading DLLs via System.load() under a directory with a unicode
// name will fail on windows, so use a hash code of the user's
// name in case the user's name contains non-ASCII characters
jnatmp = new File(tmp, "jna-" + System.getProperty("user.name").hashCode());
}
jnatmp.mkdirs();
if (!jnatmp.exists() || !jnatmp.canWrite()) {
jnatmp = tmp;
}
}
if (!jnatmp.exists()) {
throw new IOException("JNA temporary directory '" + jnatmp + "' does not exist");
}
if (!jnatmp.canWrite()) {
throw new IOException("JNA temporary directory '" + jnatmp + "' is not writable");
}
return jnatmp;
}
/** Remove all marked temporary files in the given directory. */
static void removeTemporaryFiles() throws IOException {
File dir = getTempDir();
FilenameFilter filter = new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".x") && name.startsWith(JNA_TMPLIB_PREFIX);
}
};
File[] files = dir.listFiles(filter);
for (int i=0;files != null && i < files.length;i++) {
File marker = files[i];
String name = marker.getName();
name = name.substring(0, name.length()-2);View on GitHub (pinned to d036ad9781)
Solutions
- chown/chmod the temp directory so the JVM user can write to it (e.g. chmod 1777 like /tmp).
- Point JNA at a writable directory with -Djna.tmpdir=/path/writable (or JNA_TMPDIR env var).
- Run the process under a user that owns or can write to java.io.tmpdir.
- Prefer bundling the native library on java.library.path or use OSGi-native bundling so JNA does not need to extract to a temp dir.
Example fix
// before ls -ld /opt/jnatmp # drwxr-xr-x root root; app runs as 'appuser' -> not writable // after sudo chown appuser /opt/jnatmp java -Djna.tmpdir=/opt/jnatmp -jar app.jar
Defensive patterns
Strategy: validation
Validate before calling
File dir = new File(System.getProperty("jna.tmpdir",
System.getProperty("java.io.tmpdir")));
if (dir.isDirectory() && !dir.canWrite()) {
throw new IllegalStateException("jna.tmpdir must be writable by user " + System.getProperty("user.name"));
} Try / catch
try {
MyLib lib = Native.load("mylib", MyLib.class);
} catch (IOException e) {
if (e.getMessage().contains("is not writable")) {
System.setProperty("jna.tmpdir", "/var/tmp/jna");
// retry load
} else { throw e; }
} Prevention
- Run the JVM under a user that owns or can write to the temp dir; mirror /tmp permissions (1777).
- Mount a writable volume and point -Djna.tmpdir at it in hardened containers.
- Check canWrite() on the configured dir during application startup, before first native call.
- Avoid shared temp dirs created by other users with restrictive umasks.
When it happens
Trigger: First JNA library load when the resolved temp directory (jna.tmpdir or jnatmp* under java.io.tmpdir) exists but is not writable by the JVM's OS user.
Common situations: Running a JVM as a non-root user while the temp dir is root-owned, hardened containers with read-only volumes, or a shared jna.tmpdir created earlier by another user with restrictive permissions.
Understand the failure class
Background: "Permission denied" / "Failed to write" file errors: why a library can't write its files to disk (EACCES, EPERM, ENOSPC) and how to fix them — this error's family across 43 libraries.
Related errors
- JNA temporary directory 'jnatmp' does not exist
- Win32Exception from native GetLastError after OpenProcess fa
- Win32Exception from native GetLastError after OpenThread fai
- No trash location found (define fileutils.trash to be the pa
- The following files could not be trashed: " + failed
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/13e98f8f5cb2b351.
Report an issue: GitHub.