🔗 What is a Native Method?
A native method is a method declared in Java, but implemented in a language like C or C++. These methods are usually marked with the native
keyword, for example:
public class Example {
public native void doSomethingNative();
}
⚙️ How the JVM Handles Native Method Calls
Step 1: Declaration in Java Code
You declare a method as native
in your Java code, meaning the method body is not written in Java — the JVM knows it has to delegate this call to native (platform-specific) code.
Step 2: Native Code Implementation
The actual implementation is written in a native language, usually C or C++. This implementation can directly access OS resources, hardware, or existing native libraries.
Step 3: Loading the Native Library
Before you can call the native method, the JVM must load the corresponding native library using:
System.loadLibrary("libraryName");
Step 4: Method Table Linking (JNI)
Once the library is loaded, the JVM links the native method to the correct function pointer in the native library. This is done using the Java Native Interface (JNI).
- JNI defines a standard way for Java code to call native code and vice versa.
- The native function signature must match what the JVM expects — this includes:
- Naming convention (
Java_package_class_method
) - Parameter and return types mapped to JNI types (like
jstring
,jint
, etc.)
- Naming convention (
Example C function for a Java method:
JNIEXPORT void JNICALL Java_Example_doSomethingNative(JNIEnv *env, jobject thisObj) {
// Native implementation
}
Step 5: Invocation
When the Java code calls the native
method, the JVM:
✅ Looks up the native method in an internal method table.
✅ Uses a function pointer to jump directly to the native code.
✅ Converts arguments from Java types (like String
) into JNI types (like jstring
).
✅ Transfers control to the native function.
Step 6: Native Method Execution
- The native method runs outside the JVM — in native code, you have direct access to system resources.
- You can still use the
JNIEnv
pointer to interact with the JVM, if needed (like calling back into Java).
Step 7: Return and Cleanup
- After the native method finishes, the native return value (if any) is converted back into a Java type.
- The JVM resumes execution as if a regular Java method had returned.
🚀 Quick Visualization
+------------------+
| Java Code |
| (native method) |
+------------------+
|
v
+------------------+
| JVM |
| (Method table + |
| JNI glue code) |
+------------------+
|
v
+------------------+
| Native Library |
| (C/C++ code) |
+------------------+
📜 Example Flow
public class Example {
static {
System.loadLibrary("mylib"); // Load native code
}
public native void doSomethingNative(); // Native method
}
Native C code:
#include <jni.h>
#include "Example.h"
JNIEXPORT void JNICALL Java_Example_doSomethingNative(JNIEnv *env, jobject obj) {
printf("Hello from native code!\n");
}
✅ Summary Table
Step | What Happens |
---|---|
Declare | Java defines a native method. |
Implement | Native code provides real implementation. |
Load | System.loadLibrary() loads the native library. |
Link | JVM links the method to native code (via JNI). |
Call | JVM converts arguments and calls native code. |
Return | Native method returns result to JVM. |
⚠️ Things to Watch Out For
- Crashes in native code will crash the whole JVM (unlike exceptions in Java).
- Manual memory management is required in native code.
- JNI is low-level and can be error-prone — careful coding is needed to avoid leaks or undefined behavior.