java-native-access/jna · error · Win32Exception
Win32Exception from native GetLastError after SetPriorityCla
Error message
Win32Exception from native GetLastError after SetPriorityClass (background mode) failed
What it means
setCurrentProcessBackgroundMode(boolean) maps 'enable' to PROCESS_MODE_BACKGROUND_BEGIN or PROCESS_MODE_BACKGROUND_END and calls SetPriorityClass on the current process. If the native call returns FALSE, the library throws a Win32Exception from GetLastError(). Background-begin mode requires elevated privileges and a process that is not a background process already; background-end fails when background mode was never started.
Source
Thrown at contrib/platform/src/com/sun/jna/platform/win32/Kernel32Util.java:1300
if (!isValidPriorityClass(dwPriorityClass)) {
throw new IllegalArgumentException("The given priority value is invalid!");
}
if (!Kernel32.INSTANCE.SetPriorityClass(Kernel32.INSTANCE.GetCurrentProcess(), dwPriorityClass)) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}
}
/**
* Enables or disables "background" processing mode for the current process
*
* @param enable If true, enables "background" processing mode, otherwise disables it.
* @throws Win32Exception if an error occurs.
*/
public static void setCurrentProcessBackgroundMode(final boolean enable) {
// Note: PROCESS_MODE_BACKGROUN_{BEGIN,END} only works with the "current" process handle!
final DWORD dwPriorityClass = enable ? Kernel32.PROCESS_MODE_BACKGROUND_BEGIN : Kernel32.PROCESS_MODE_BACKGROUND_END;
if (!Kernel32.INSTANCE.SetPriorityClass(Kernel32.INSTANCE.GetCurrentProcess(), dwPriorityClass)) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}
}
/**
* Gets the priority value of the current thread.
*
* @return The priority value of the current thread.
* @throws Win32Exception if an error occurs.
*/
public static int getCurrentThreadPriority() {
final int nPriority = Kernel32.INSTANCE.GetThreadPriority(Kernel32.INSTANCE.GetCurrentThread());
if (!isValidThreadPriority(nPriority)) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}
return nPriority;
}
/**View on GitHub (pinned to d036ad9781)
Solutions
- Ensure every setCurrentProcessBackgroundMode(true) is paired with exactly one (false) call in a finally block.
- Run elevated if enabling background mode, since BACKGROUND_BEGIN requires additional privilege.
- Check Win32Exception.getErrorCode(): ERROR_PROCESS_MODE_ALREADY_BACKGROUND (402) means begin was called twice; ERROR_PROCESS_MODE_NOT_BACKGROUND (403) means end without begin.
- Wrap in try-catch and fall back to normal priority classes if the mode switch fails.
Example fix
// before
Kernel32Util.setCurrentProcessBackgroundMode(true);
// after
boolean bg = false;
try {
Kernel32Util.setCurrentProcessBackgroundMode(true);
bg = true;
// ... disk-heavy work ...
} finally {
if (bg) Kernel32Util.setCurrentProcessBackgroundMode(false);
} Defensive patterns
Strategy: try-catch
Validate before calling
// background begin requires elevation:
// if (!isAdmin()) throw new IllegalStateException("background mode requires elevation");
// track state to avoid unbalanced calls:
if (enable && backgroundModeActive) { throw new IllegalStateException("background mode already active"); }
if (!enable && !backgroundModeActive) { return; } // nothing to end Try / catch
try {
Kernel32Util.setCurrentProcessBackgroundMode(true);
} catch (Win32Exception e) {
// 402 = already background, 403 = not background (for 'end')
log.warn("Background mode switch failed: {}", e.getErrorCode());
} Prevention
- Balance begin/end calls; put the 'end' call in a finally block.
- Require elevation before enabling PROCESS_MODE_BACKGROUND_BEGIN.
- Track mode state in a flag to avoid double-begin/end sequences.
- Map error codes 402/403 (already/not background) to clear log messages.
When it happens
Trigger: Calling Kernel32Util.setCurrentProcessPriority-style background mode via Kernel32Util.setCurrentProcessBackgroundMode(true) without elevation, or calling setCurrentProcessBackgroundMode(false) when background mode was never enabled — both make SetPriorityClass fail with a native error.
Common situations: Non-admin processes attempting PROCESS_MODE_BACKGROUND_BEGIN (needs SeIncreaseBasePriorityPrivilege); unbalanced begin/end calls across code paths; Windows versions/job objects that reject the mode constants.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- Win32Exception from native GetLastError when GetPriorityClas
- Win32Exception from native GetLastError after SetPriorityCla
- Win32Exception from native GetLastError after SetThreadPrior
- LookupAccountNameW was expected to fail with ERROR_INSUFFICI
- Expected GetTokenInformation to fail with ERROR_INSUFFICIENT
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/4da809adbff430ba.
Report an issue: GitHub.