java-native-access/jna · error · Win32Exception
Win32Exception from native GetLastError after…
Error message
Win32Exception from native GetLastError after Module32FirstW failed
What it means
Kernel32Util.getModules throws this Win32Exception when Kernel32.INSTANCE.Module32FirstW returns false after a valid snapshot was created. The native GetLastError code explains why the first module entry could not be retrieved (e.g. ERROR_ACCESS_DENIED or a snapshot invalidated because the target process exited).
Solutions
- Treat this as a race: catch Win32Exception and skip the process if it likely exited
- Check errorCode and map ERROR_NO_MORE_FILES/ERROR_INVALID_PARAMETER to 'empty module list' rather than a hard failure
- Retry getModules once after a short delay for volatile PIDs
- Re-check the PID's existence (OpenProcess) before retrying
Example fix
// before
List<Tlhelp32.MODULEENTRY32W> mods = Kernel32Util.getModules(pid);
// after
List<Tlhelp32.MODULEENTRY32W> mods;
try {
mods = Kernel32Util.getModules(pid);
} catch (Win32Exception e) {
mods = Collections.emptyList(); // process exited before first module read
} Defensive patterns
Strategy: retry
Validate before calling
HANDLE proc = Kernel32.INSTANCE.OpenProcess(WinNT.PROCESS_QUERY_LIMITED_INFORMATION, false, new DWORD(pid)); if (proc == null) return Collections.emptyList(); // target exited before snapshot Kernel32.INSTANCE.CloseHandle(proc);
Type guard
null
Try / catch
try {
mods = Kernel32Util.getModules(pid);
} catch (Win32Exception e) {
// process likely exited between snapshot and Module32FirstW
mods = Collections.emptyList();
} Prevention
- Expect races with short-lived processes and retry once
- Treat empty/failed first reads as 'process vanished', not a system error
- Avoid enumerating modules of processes you know are starting/stopping
- Log errorCode to distinguish transient vs permission problems
When it happens
Trigger: Calling Kernel32Util.getModules(processID) where CreateToolhelp32Snapshot succeeded but Module32FirstW fails — typically because the target process terminated between snapshot creation and the first read, or the module list became inaccessible.
Common situations: Short-lived processes exiting between snapshot and Module32FirstW; processes still initializing with no modules listed yet; permission changes on the target process.
Related errors
- Win32Exception from GetLastError after Module32NextW failed…
- Win32Exception from native GetLastError after…
- LockResource returned null.
- Win32Exception from native GetLastError after…
- Win32Exception from native GetLastError after…
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/35f189258b173229.
Report an issue: GitHub.
Appendix: source
Thrown at contrib/platform/src/com/sun/jna/platform/win32/Kernel32Util.java:1180
/**
* Returns all the executable modules for a given process ID.<br>
*
* @param processID
* The process ID to get executable modules for
* @return All the modules in the process.
*/
public static List<Tlhelp32.MODULEENTRY32W> getModules(int processID) {
HANDLE snapshot = Kernel32.INSTANCE.CreateToolhelp32Snapshot(Tlhelp32.TH32CS_SNAPMODULE, new DWORD(processID));
if (snapshot == null) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}
Win32Exception we = null;
try {
Tlhelp32.MODULEENTRY32W first = new Tlhelp32.MODULEENTRY32W();
if (!Kernel32.INSTANCE.Module32FirstW(snapshot, first)) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}
List<Tlhelp32.MODULEENTRY32W> modules = new ArrayList<>();
modules.add(first);
Tlhelp32.MODULEENTRY32W next = new Tlhelp32.MODULEENTRY32W();
while (Kernel32.INSTANCE.Module32NextW(snapshot, next)) {
modules.add(next);
next = new Tlhelp32.MODULEENTRY32W();
}
int lastError = Kernel32.INSTANCE.GetLastError();
// if we got a false from Module32Next,
// check to see if it returned false because we're genuinely done
// or if something went wrong.
if (lastError != W32Errors.ERROR_SUCCESS && lastError != W32Errors.ERROR_NO_MORE_FILES) {
throw new Win32Exception(lastError);
}View on GitHub (pinned to d036ad9781)