java-native-access/jna · error · java.lang.UnsatisfiedLinkError
Library has been unloaded
Error message
Library has been unloaded
What it means
NativeLibrary.getSymbolAddress throws UnsatisfiedLinkError when the library handle is 0, meaning the library has already been disposed via dispose() (or finalization) and its native handle released. No further symbol lookups are possible on that instance.
Source
Thrown at src/com/sun/jna/NativeLibrary.java:649
* @param symbolName
* @return Pointer representing the global variable address
* @throws UnsatisfiedLinkError if the symbol is not found
*/
public Pointer getGlobalVariableAddress(String symbolName) {
try {
return new Pointer(getSymbolAddress(symbolName));
} catch(UnsatisfiedLinkError e) {
throw new UnsatisfiedLinkError("Error looking up '" + symbolName + "': " + e.getMessage());
}
}
/**
* Used by the Function class to locate a symbol
* @throws UnsatisfiedLinkError if the symbol can't be found
*/
long getSymbolAddress(String name) {
if (handle == 0) {
throw new UnsatisfiedLinkError("Library has been unloaded");
}
return this.symbolProvider.getSymbolAddress(handle, name, NATIVE_SYMBOL_PROVIDER);
}
@Override
public String toString() {
return "Native Library <" + libraryPath + "@" + handle + ">";
}
/** Returns the simple name of this library. */
public String getName() {
return libraryName;
}
/**
* Returns the file on disk corresponding to this NativeLibrary instance.
* If this NativeLibrary represents the current process, this function will return null.
*/
public File getFile() {
if (libraryPath == null)View on GitHub (pinned to d036ad9781)
Solutions
- Do not dispose the NativeLibrary while Functions derived from it are still in use
- Re-acquire the library with NativeLibrary.getInstance(name) after disposal
- Reorder shutdown logic so library disposal is the last step
- Check for accidental dispose() calls (e.g. in finally blocks or finalizers)
Example fix
// before
lib.dispose();
Function f = lib.getFunction("foo"); // throws
// after
Function f = lib.getFunction("foo");
f.invoke(...);
lib.dispose(); // dispose last Defensive patterns
Strategy: validation
Validate before calling
if (lib != null && isDisposed(lib)) {
lib = NativeLibrary.getInstance("mylib");
} Try / catch
try {
Function f = lib.getFunction("foo");
} catch (UnsatisfiedLinkError e) {
if (e.getMessage().contains("unloaded")) {
lib = NativeLibrary.getInstance("mylib"); // reacquire
}
} Prevention
- Treat NativeLibrary instances as owning their Functions; dispose only at final shutdown
- Do not cache Function objects beyond the library's lifetime
- Avoid calling dispose() in finally blocks of code that still uses functions
When it happens
Trigger: Calling lib.getFunction(...), lib.getGlobalVariableAddress(...), or invoking a previously obtained Function after calling lib.dispose(); holding a Function object past the library's cleanup.
Common situations: Explicit NativeLibrary.dispose() in shutdown code followed by late callbacks or pending invocations; garbage collection finalizing the library while a Function is still referenced; reusing a cached library object after unload.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Class cls.getName() is not currently registered
- Component must be displayable
- JNA: Can't attach native thread to VM on unload
- JNA: could not detach thread on unload
- No support for " + os
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/7ee9560a6a451894.
Report an issue: GitHub.