LWJGL 3 is a ground-up redesign that is not backwards compatible with LWJGL 2. The architecture, packaging, windowing model, memory model, and package structure all changed. This page summarises what changed and provides a mapping of common API calls to help you port existing code.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.
Major changes from LWJGL 2
1. Modular packaging
LWJGL 2 was distributed as a single JAR. LWJGL 3 is split into independent modules — one per binding — so you only include what you use. The core module (lwjgl.jar) is required; every binding (GLFW, OpenGL, Vulkan, etc.) is a separate optional artifact.
Use the LWJGL build configurator to generate Maven or Gradle declarations for exactly the modules your project needs.
2. Explicit off-heap memory management
LWJGL 2 usedBufferUtils.createByteBuffer(), which allocated Java NIO ByteBuffer instances backed by the GC-managed heap. LWJGL 3 exposes a full explicit allocator:
MemoryUtil.memAlloc/memFree— Allocate and free off-heap buffers manually. Every allocation must be freed or it leaks.MemoryStack— A thread-local stack allocator for short-lived allocations. Use try-with-resources; the memory is reclaimed automatically when the block exits.
3. Windowing moved to GLFW (or SDL)
LWJGL 2 provided its ownDisplay class for window creation and management. LWJGL 3 delegates this to external libraries. GLFW is the most commonly used option and is bundled as the lwjgl-glfw module. SDL 3 is also available as of LWJGL 3.4.0.
4. Input handling through GLFW callbacks
LWJGL 2 providedKeyboard and Mouse classes with polling-style methods. LWJGL 3 uses GLFW callback functions instead. You register a callback once and GLFW calls it when an event fires.
5. New package structure
All LWJGL 3 classes live underorg.lwjgl.*. The top-level package hierarchy changed significantly:
| LWJGL 2 package | LWJGL 3 package |
|---|---|
org.lwjgl.opengl | org.lwjgl.opengl (same name, different classes) |
org.lwjgl.input | removed — use org.lwjgl.glfw callbacks |
org.lwjgl (Display, etc.) | removed — use org.lwjgl.glfw |
org.lwjgl.util.* | removed or replaced |
6. Callbacks are explicit and must be freed
In LWJGL 3, every callback object allocates a native stub. That stub must be freed when it is no longer needed, otherwise it leaks native memory.7. Library loading via Configuration
LWJGL 2 usedSystem.loadLibrary conventions. LWJGL 3 loads natives from the classpath (from the natives JAR) automatically, and exposes the Configuration class for customisation:
API mapping table
| LWJGL 2 | LWJGL 3 |
|---|---|
Display.create() | glfwCreateWindow(width, height, title, 0, 0) |
Display.update() | glfwSwapBuffers(window) + glfwPollEvents() |
Display.destroy() | glfwDestroyWindow(window) + glfwTerminate() |
Keyboard.isKeyDown(key) | key state via glfwSetKeyCallback or glfwGetKey |
Mouse.getDX() / getDY() | cursor delta via glfwSetCursorPosCallback |
BufferUtils.createByteBuffer(n) | MemoryUtil.memAlloc(n) (manual free) or MemoryStack.malloc(n) |
BufferUtils.createIntBuffer(n) | MemoryUtil.memAllocInt(n) or MemoryStack.mallocInt(n) |
GL11.glViewport(...) | GL11.glViewport(...) (same call, different import path) |
Migrating between LWJGL 3.x releases
From 3.3.x to 3.4.x
LWJGL 3.4.0 was released on 2026 Jan 18 and includes the following breaking changes: Removed deprecated struct allocation methods ThemallocStack and callocStack methods on all struct classes were removed. These were deprecated in 3.3.0 when shorter malloc and calloc equivalents (without the “Stack” suffix) were introduced. Replace all calls:
lwjgl-cudalwjgl-libdividelwjgl-meowlwjgl-nanovg(Blendish and OUI portions only; NanoVG itself remains)lwjgl-openvrlwjgl-ovrlwjgl-sselwjgl-tootle
- RenderDoc bindings (
lwjgl-renderdoc) - SDL 3 bindings (
lwjgl-sdl) - libspng bindings (
lwjgl-spng)
--sun-misc-unsafe-memory-access=deny. No code changes are required if you do not use internal unsafe APIs.
OpenCL cl_ulong constants
The carrier type of cl_ulong constants changed from int to long to prevent unintentional sign extension for negative values. Update any comparisons or casts that assumed an int.
Vulkan on macOS x64
MoltenVK on x64 now requires macOS 11.0 or later (previously 10.13).
API documentation removed from Javadoc
LWJGL 3.4.0 no longer includes generated API documentation in javadoc form. Native function signatures for downcalls and upcalls are still present, and each module’s package-info javadoc now links to official API documentation, source repositories, and guides.
From 3.4.0 to 3.4.1
LWJGL 3.4.1 was released on 2026 Feb 03. The breaking changes are limited to the Shaderc and SPIRV Tools bindings:- Shaderc/glslang — The resource limits interface (
resource_limits_c.h) was extracted into a separate class. A newConfiguration.GLSLANG_RESOURCE_LIBRARY_NAMEoption was added to configure the library path. - Shaderc/SPIRV Tools — The optimizer interface was extracted into a separate class. A new
Configuration.SPIRV_TOOLS_OPTIMIZER_LIBRARY_NAMEoption was added.