java-native-access/jna · error · Win32Exception
Win32Exception from native GetLastError when SizeofResource
Error message
Win32Exception from native GetLastError when SizeofResource returned 0
What it means
Kernel32Util throws this Win32Exception when Kernel32.INSTANCE.SizeofResource returns 0 after the resource was found and loaded. A zero size means the resource has no data or the size could not be determined; the native GetLastError code is wrapped to expose the underlying reason.
Source
Thrown at contrib/platform/src/com/sun/jna/platform/win32/Kernel32Util.java:1022
} catch (NumberFormatException e) {
n = new Memory(Native.WCHAR_SIZE * (name.length() + 1));
n.setWideString(0, name);
}
HRSRC hrsrc = Kernel32.INSTANCE.FindResource(target, n, t);
if (hrsrc == null) {
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) {View on GitHub (pinned to d036ad9781)
Solutions
- Catch Win32Exception and check errorCode (e.g. ERROR_INVALID_HANDLE 6)
- Ensure the same HMODULE instance is used for all calls in the sequence
- Treat size 0 as 'empty resource' and skip/handle gracefully before copying bytes
- Re-extract the resource from a known-good copy of the binary
Example fix
// before
byte[] data = Kernel32Util.getResource(h, type, name); // throws on empty resource
// after
try {
byte[] data = Kernel32Util.getResource(h, type, name);
} catch (Win32Exception e) {
if (e.getErrorCode().intValue() == WinError.ERROR_INVALID_HANDLE) {
throw new IllegalStateException("Resource size could not be read", e);
}
throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check by loading as datafile and probing size indirectly is not exposed;
// instead guard the module handle:
if (target == null) throw new IllegalArgumentException("target module handle must not be null"); Type guard
boolean canSize(HMODULE target, HRSRC hrsrc) {
DWORD sz = Kernel32.INSTANCE.SizeofResource(target, hrsrc);
return sz != null && sz.intValue() > 0;
} Try / catch
try {
byte[] data = Kernel32Util.getResource(h, type, name);
} catch (Win32Exception e) {
// size 0 / invalid handle during SizeofResource
log.warn("Cannot size resource " + name + " code=" + e.getErrorCode(), e);
throw e;
} Prevention
- Use the same HMODULE for the whole Find/Load/Size/Lock sequence
- Treat zero-size as an 'empty resource' condition in your own pre-checks
- Avoid double-loading the module with different flags
- Validate downloaded/shipped binaries before reading resources
When it happens
Trigger: Calling Kernel32Util.getResource(...) where FindResource and LoadResource succeeded but SizeofResource(target, hrsrc) returns 0 — zero-length resources, or an hrsrc/module handle combination the OS cannot size (e.g. handle from a different module instance).
Common situations: Reading resources from a module loaded twice with different flags so the HRSRC belongs to another HMODULE; resources intentionally stored empty; maliciously or accidentally stripped resource sections.
Related errors
- Win32Exception from native GetLastError after FindResource f
- Win32Exception from native GetLastError after LoadResource f
- LockResource returned null.
- Win32Exception from native GetLastError after EnumResourceTy
- Win32Exception from native GetLastError after EnumResourceNa
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/336ded1d5dff8f97.
Report an issue: GitHub.