JNI Registers Native Methods
Register native C++ methods for Java to access them.
1. Introduction
In Android applications, interacting with native C++ code through the Java Native Interface (JNI) is common, as many powerful and efficient libraries—especially those for image processing, rendering, and video/audio processing—are implemented in C++.
JNI allows Java code to call and be called by native code. In Java, we can declare a native method that is implemented in C++ code.
1 | public class JNIActivity extends AppCompatActivity { |
Accordingly, we can add a C++ module and implement the native method defined in Java.
1 | extern "C" |
In JNI, the naming convention Java_<package>_<class>_<methodName>
is required to link Java methods with their corresponding native C++ implementations. This naming scheme helps JNI locate the correct C++ function when the native method is called from Java. JNI’s naming convention also helps avoid function name collisions across packages or classes. For instance, if you have a similar method in a different class or package, the convention makes sure each native method has a unique name based on its Java class and package.
The JVM automatically links the native methods to their implementations by name when you call the System.loadLibrary()
method to load your shared library.
2. JNI_OnLoad
When to use JNI_OnLoad
?
JNI_OnLoad
is a special function in JNI that is automatically called when a native shared library is loaded into the JVM through System.loadLibrary
in Java.
JNI_OnLoad
is typically used if:
- You want to customize the registration process or register multiple methods at once (e.g., for complex scenarios or performance optimization).
- You don’t want to follow the JNI naming convention and prefer more control over method registration (e.g., for flexibility or to avoid long, cumbersome method names).
- You have initialization code to run when the library is loaded.
We are going to discuss more about the second scenario, where we aim to establish custom naming conventions for our native methods. We still keep the same method name in Java.
1 | public native String getMessageFromJNI(); |
However, in native C++ code, we have a new customized name for the corresponding java method.
1 | jstring sendMessage(JNIEnv *env, jobject thiz) { |
If we try to use getMessageFromJNI()
anywhere in Java code, we will get a No implementation
error message. The way to link them is to register native methods dynamically using RegisterNatives
in JNI_OnLoad
. This function lets you map Java native methods to any C++ function, bypassing the strict naming convention.
1 | jstring sendMessage(JNIEnv *env, jobject thiz) { |
- JNI Version Check: The JNI_OnLoad function checks that the JNI version is compatible (e.g., JNI_VERSION_1_6).
- Find Java Class: FindClass locates the Java class JNIActivity in which the native methods are declared.
- Define Native Methods: The JNINativeMethod struct associates Java method names with the corresponding C++ functions. Each entry contains:
- Java method name (as a string)
- Method signature (in JNI format)
- Pointer to the native function
- Register Native Methods: RegisterNatives links the Java method names to the C++ implementations.
JNI Registers Native Methods
http://chuzcjoe.github.io/2024/10/23/misc-jni-register-native/