Learn · concepts
What Is JNI? Java Native Interface for Modders
JNI (Java Native Interface) is Java's built-in bridge for calling C/C++ from the JVM and back. It is the standard way a Minecraft mod loads a native library.
What is JNI in plain terms?
JNI (Java Native Interface) is the part of Java that connects two worlds: managed bytecode on the JVM and compiled machine code written in C or C++. A method gets the native keyword and no body, and at runtime the JVM links it to a matching function in a loaded native library. From there both sides trade arguments and return values.
The boundary is not one-directional. The native function receives a JNIEnv pointer, and that handle is the gateway back into Java: it exposes calls for reading and writing Java fields, invoking Java methods, constructing objects, and raising exceptions. So the same bridge that lets Java call out also lets C call in.
Why would a Minecraft mod or client touch native code?
Most Java never needs JNI. A mod reaches for it when the JVM alone cannot do the job, usually graphics, audio, OS integration, or a routine that has to be fast. The native library does the heavy lifting and JNI is the standard way to load and call it.
Reuse a proven C library
A mature native codebase already solves the problem. Rewriting it in Java is wasted effort, so the mod binds to it instead.
Reach the operating system
Some platform features have no pure-Java API. A native call becomes the only route to them.
Speed a hot path
A tight numeric or low-level routine can run faster as compiled native code than as bytecode on the JVM.
Drive hardware and drivers
Rendering, sound, and device access frequently sit behind native libraries that JNI exposes to the Java side.
How does a JNI call work end to end?
The flow is identical on every platform: declare the method in Java, compile a matching C function into a shared library, load it at runtime, let the JVM link them by name, then call across. Function names follow a fixed pattern so the JVM can resolve them, and a generated header spells out the exact signature to implement.
| Step | What happens |
|---|---|
| Declare | A Java method is written with the native keyword and left empty on the Java side. |
| Build | A C or C++ function is compiled into a shared library: .dll on Windows, .so on Linux, .dylib on macOS. |
| Load | Java calls System.loadLibrary to load that library while the program runs. |
| Link | The JVM matches each native method to its C function by a name-mangled signature. |
| Call | Java invokes the method; control crosses into native code and returns with a result. |
What does JNI cost you?
JNI is powerful and it has sharp edges. Because native code runs outside the JVM's safety net, a fault there crashes the entire process rather than throwing a catchable exception. Memory the native side allocates is invisible to the garbage collector, so leaks pile up unless they are freed by hand. Each crossing carries overhead, which makes calling across the boundary inside a tight loop expensive. And native builds are platform-locked: a Windows .dll will not load on Linux without a separate compile.
What it buys
- Direct access to existing C and C++ libraries
- A path to OS and hardware features the JVM cannot reach
- Native-speed execution for the hottest routines
What it costs
- A native crash can take down the whole JVM
- Manual memory management with no garbage-collector backstop
- Per-platform builds to maintain and ship
- Boundary-crossing overhead in hot loops
JNI vs the Foreign Function and Memory API
JNI is the original mechanism, but it is no longer the only one. Newer Java releases ship the Foreign Function and Memory (FFM) API, designed to call native code with less boilerplate and tighter safety guarantees. JNI still dominates existing toolchains because it is everywhere and thoroughly understood.
| JNI | FFM API | |
|---|---|---|
| Age | Original, present since early Java | Modern, added in recent releases |
| Boilerplate | Generated headers, name-mangled C functions | Method handles defined in Java, no glue C |
| Memory safety | Manual; mistakes can corrupt the JVM | Bounded segments with stronger checks |
| Adoption | Ubiquitous across existing libraries | Growing, newer codebases |
FAQ
It is built in. JNI ships with the JDK and the JVM, so the Java side needs nothing extra. Compiling the native half still requires a C or C++ toolchain for each target platform.
No. The Java half stays portable, but a native library is compiled for one operating system and CPU. Shipping cross-platform means building and bundling a separate .dll, .so, and .dylib.
No. JNI is the original mechanism. Recent Java releases add the Foreign Function and Memory API, which aims to be safer and require less boilerplate, but JNI remains widely deployed and well understood.
When the JVM cannot do something directly (talk to a GPU or audio backend, hit a platform-only API, or run a performance-critical routine), a mod loads a native library and calls into it through JNI.
Built by people who actually read the JVM internals.