java-native-access/jna · error · IllegalStateException

LockResource returned null.

Error message

LockResource returned null.

What it means

Kernel32Util throws this IllegalStateException (not a Win32Exception) when Kernel32.INSTANCE.LockResource returns null after the resource was loaded. MSDN does not document LockResource as setting GetLastError, so JNA signals it as an internal invariant violation instead of a native-error wrapper.

Source

Thrown at contrib/platform/src/com/sun/jna/platform/win32/Kernel32Util.java:1029

                throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
            }

            // according to MSDN, on 32 bit Windows or newer, calling FreeResource() is not necessary - and in fact does nothing but return false.
            HANDLE loaded = Kernel32.INSTANCE.LoadResource(target, hrsrc);
            if (loaded == null) {
                throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
            }

            length = Kernel32.INSTANCE.SizeofResource(target, hrsrc);
            if (length == 0) {
                throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
            }

            // MSDN: It is not necessary to unlock resources because the system automatically deletes them when the process that created them terminates.
            // MSDN does not say that LockResource sets GetLastError
            start = Kernel32.INSTANCE.LockResource(loaded);
            if (start == null) {
                throw new IllegalStateException("LockResource returned null.");
            }
            // have to capture it into a byte array before you free the library, otherwise bad things happen.
            results = start.getByteArray(0, length);
        } catch (Win32Exception we) {
            err = we;
        } finally {
            // from what I can tell on MSDN, the only thing that needs cleanup on this is the HMODULE from LoadLibrary
            if (target != null) {
                if (!Kernel32.INSTANCE.FreeLibrary(target)) {
                    Win32Exception we = new Win32Exception(Kernel32.INSTANCE.GetLastError());
                    if (err != null) {
                        we.addSuppressedReflected(err);
                    }
                    throw we;
                }
            }
        }

View on GitHub (pinned to d036ad9781)

Solutions

  1. Verify no concurrent FreeLibrary/unload invalidates the loaded handle
  2. Check any custom Kernel32 interface mapping returns a proper Pointer for LockResource
  3. Catch IllegalStateException and retry resource extraction once
  4. Report as a JVM/native-level failure if reproducible — the preceding calls succeeded

Example fix

// before
byte[] data = Kernel32Util.getResource(h, type, name); // may throw IllegalStateException
// after
try {
    byte[] data = Kernel32Util.getResource(h, type, name);
} catch (IllegalStateException e) {
    throw new IllegalStateException("LockResource failed for resource " + name + " in " + h, e);
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (target == null) throw new IllegalArgumentException("module handle required");
// ensure the module stays loaded: hold a reference and no FreeLibrary in this scope

Type guard

null

Try / catch

try {
    byte[] data = Kernel32Util.getResource(h, type, name);
} catch (IllegalStateException e) {
    // LockResource returned null despite successful load — native/JVM-level anomaly
    throw new IllegalStateException("resource lock failed for " + name, e);
}

Prevention

When it happens

Trigger: Calling Kernel32Util.getResource(...) where FindResource/LoadResource/SizeofResource all succeeded but LockResource(loaded) returns null — effectively only when the HANDLE passed is invalid, which under normal use cannot happen because it was just returned by LoadResource.

Common situations: Very rare in practice: memory pressure or corrupted process state, custom Kernel32 mappings that mishandle HMODULE/HRSRC types, running the extraction logic on a concurrently-unloaded module.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12). Data as JSON: /api/errors/8640ebd29df18b01. Report an issue: GitHub.