Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/LWJGL/lwjgl3/llms.txt

Use this file to discover all available pages before exploring further.

LWJGL 3 exposes runtime configuration through two equivalent mechanisms: JVM system properties (set on the command line before the process starts) and the Configuration class in org.lwjgl.system (set programmatically at startup). Both mechanisms read from the same state; a Configuration field simply wraps its corresponding property name so your IDE can autocomplete it.

Static vs. dynamic options

Every configuration option falls into one of two categories.

Static options

Read once, the first time the relevant LWJGL subsystem initializes, and then cached in static final fields. You must set these before any other LWJGL class is loaded. Examples: DEBUG, STACK_SIZE, MEMORY_ALLOCATOR.

Dynamic options

Read on every access. You can change these at any point during the application’s lifetime. Examples: LIBRARY_PATH, DEBUG_MEMORY_ALLOCATOR_FAST.
Static options that are set after the relevant class has already been initialized will have no effect. Configure them at the very top of your main method, before creating any window, context, or buffer.

Setting options

java -Dorg.lwjgl.util.Debug=true \
     -Dorg.lwjgl.system.stackSize=128 \
     -jar myapp.jar

Core options

Takes priority over java.library.path when LWJGL searches for native shared libraries. Accepts one or more paths separated by the platform path separator (: on Unix, ; on Windows).Usage: Dynamic
-Dorg.lwjgl.librarypath=/opt/lwjgl/native:/usr/local/lib
Configuration.LIBRARY_PATH.set("/opt/lwjgl/native");
Changes the name of the temporary directory created by LWJGL when extracting bundled shared libraries from JAR files. Defaults to lwjgl_<username>.Usage: Dynamic
Configuration.SHARED_LIBRARY_EXTRACT_DIRECTORY.set("myapp_natives");
Sets the absolute path where LWJGL extracts bundled natives. When unset, LWJGL tries java.io.tmpdir, the working directory, user.home, and finally a JVM temp directory in that order.Usage: Dynamic
Configuration.SHARED_LIBRARY_EXTRACT_PATH.set("/var/cache/myapp/natives");
Replaces the allocator used by MemoryUtil (memAlloc, memFree, etc.). Supported string values: jemalloc, rpmalloc, system. Can also be set programmatically to a MemoryAllocator instance.Usage: Static
-Dorg.lwjgl.system.allocator=jemalloc
Configuration.MEMORY_ALLOCATOR.set("jemalloc");
Sets the size in kilobytes of each thread-local MemoryStack instance. Defaults to 64 (64 KB). Increase this if you see stack overflow errors from deeply nested struct allocations.Usage: Static
-Dorg.lwjgl.system.stackSize=128
Configuration.STACK_SIZE.set(128);

Debug options

Master debug switch. When enabled, LWJGL prints informational messages to the debug stream and enables additional runtime checks (some expensive). Required for DEBUG_LOADER and DEBUG_FUNCTIONS to have any effect.Usage: Static
-Dorg.lwjgl.util.Debug=true
Configuration.DEBUG.set(true);
Tracks every memAlloc / memFree call and reports leaks at JVM exit. Each allocation records a stack trace, so performance impact can be significant. See also DEBUG_MEMORY_ALLOCATOR_FAST for a lighter-weight alternative.Usage: Static
-Dorg.lwjgl.util.DebugAllocator=true
Configuration.DEBUG_MEMORY_ALLOCATOR.set(true);
When true, skips stack trace generation for each tracked allocation. Leaks are still reported at exit, but without the originating stack trace. Toggle at runtime to minimize overhead while still detecting leaks.Usage: Dynamic
// Enable fast mode to reduce overhead during profiling
Configuration.DEBUG_MEMORY_ALLOCATOR_FAST.set(true);

// Disable to capture stack traces for a suspect section
Configuration.DEBUG_MEMORY_ALLOCATOR_FAST.set(false);
runSuspectCode();
Configuration.DEBUG_MEMORY_ALLOCATOR_FAST.set(true);
Enables debug mode for MemoryStack. When active, each push() / pop() records a stack trace. If a frame is popped in a different method than the one that pushed it, an error is reported immediately.Usage: Static
-Dorg.lwjgl.util.DebugStack=true
Configuration.DEBUG_STACK.set(true);
Prints a warning to the debug stream whenever LWJGL cannot resolve a function pointer from a shared library. Requires DEBUG to be enabled. May produce false positives for functions in unused extension classes.Usage: Static
-Dorg.lwjgl.util.Debug=true -Dorg.lwjgl.util.DebugFunctions=true
Disables LWJGL’s basic parameter validation checks (null pointer guards, range checks, etc.). These checks are cheap but add up. Safe to enable in production builds after thorough testing.Usage: Static
-Dorg.lwjgl.util.NoChecks=true

Graphics and compute explicit-init options

Several APIs that have their own initialization step default to auto-initializing the first time they are accessed. Set the corresponding _EXPLICIT_INIT option to true to take control of initialization yourself.
When true, disables automatic initialization of the EGL library. You must call EGL.create() manually before using any EGL function.Usage: Static
Configuration.EGL_EXPLICIT_INIT.set(true);
// ... later, when your EGL display is ready:
EGL.create();
When true, disables automatic initialization of the OpenAL library. You must call AL.create() / ALC.create() manually.Usage: Static
Configuration.OPENAL_EXPLICIT_INIT.set(true);
When true, disables automatic initialization of the OpenGL library. You must call GL.createCapabilities() manually after making an OpenGL context current.Usage: Static
Configuration.OPENGL_EXPLICIT_INIT.set(true);
// ... after glfwMakeContextCurrent(window):
GL.createCapabilities();
When true, disables automatic initialization of the Vulkan library. You must call VK.create() before using any Vulkan function.Usage: Static
Configuration.VULKAN_EXPLICIT_INIT.set(true);
// ... when ready:
VK.create();
When true, disables automatic initialization of the OpenCL library.Usage: Static
Configuration.OPENCL_EXPLICIT_INIT.set(true);
When true, disables automatic initialization of the OpenXR library.Usage: Static
Configuration.OPENXR_EXPLICIT_INIT.set(true);

FFM backend options

These options are relevant only when running on JDK 25+ with the FFM backend active. See FFM API support for background.
Controls the FFM Arena type used to allocate upcall stubs. Accepted values: auto (default, GC-managed), confined (thread-confined, immediate release), shared (thread-shared, immediate release but slower).Usage: Static
Configuration.FFM_UPCALL_ARENA.set("confined");
When true (default), uncaught exceptions from FFM upcalls are caught and forwarded to the exception handler rather than terminating the JVM. Set to false only when your upcall handles exceptions internally.Usage: Dynamic
Configuration.FFM_UPCALL_EXCEPTION_CATCH.set(false);
Replaces the default upcall exception handler (which prints to the debug stream). Accepts a Consumer<Throwable> instance programmatically, or a fully-qualified class name via property.Usage: Dynamic
Configuration.FFM_UPCALL_EXCEPTION_HANDLER.set(
    (Throwable t) -> myLogger.error("Uncaught exception in upcall", t)
);
Sets the nullable annotation class the runtime bindings generator uses to determine which MemorySegment parameters accept null. Defaults to auto (LWJGL scans the classpath for popular annotations). Set to none to disable auto-detection.Usage: Static
Configuration.FFM_DEFAULT_NULLABLE_ANNOTATION.set("org.jspecify.annotations.Nullable");
The following combination of options gives comprehensive diagnostics during development without requiring code changes for release builds. Passing them as JVM flags keeps your source code clean:
java \
  -Dorg.lwjgl.util.Debug=true \
  -Dorg.lwjgl.util.DebugAllocator=true \
  -Dorg.lwjgl.util.DebugStack=true \
  -Dorg.lwjgl.util.DebugFunctions=true \
  -jar myapp.jar
For production, omit all debug flags and optionally add:
java \
  -Dorg.lwjgl.util.NoChecks=true \
  -Dorg.lwjgl.system.allocator=jemalloc \
  -jar myapp.jar

Build docs developers (and LLMs) love