-
Notifications
You must be signed in to change notification settings - Fork 3
Implementing Native Methods
One of the most common tasks when writing JNI code is to implement native Java methods. SmJNI makes it very easy and straightforward. Make sure you read about Declaring Java Types and Representing Java Classes before reading this page; it builds upon information explained there.
There are 2 ways of implementing native methods in raw JNI. One is by giving special names to methods exposed from a shared library. Another is by manually registering implementations of Java methods. The first approach can be used with SmJNI, if desired, but it has many known deficiencies and is not generally recommended. SmJNI provides direct support for manual registration.
In order to register a native method using SmJNI you will need to
-
Define all the Java types used in method signature as described in Declaring Java Types. For example if the method you are implementing uses java.util.Map as an argument or return value, you will need to do something along the lines of
DEFINE_JAVA_TYPE(jMap, "java.util.Map");
-
Declare the C++ implementation using the precise mapping of Java types to C++. The C++ method will have 2 parameters in addition to whatever parameters Java method takes. For static methods these will be:
JNIEnv *, jclass
For instance methods these will be
JNIEnv *, <mapped type you defined>For example consider
class Something { native boolean instanceMethod(int i, Map m); static native boolean staticMethod(int i, Map m); }
These will require the following C++ declarations
DEFINE_JAVA_TYPE(jMap, "java.util.Map"); DEFINE_JAVA_TYPE(jSomething, "com.mystuff.Something"); jboolean instanceMethod(JNIEnv * env, jSomething obj, jint i, jMap m); jboolean staticMethod(JNIEnv * env, jclass cls, jint i, jMap m);
-
Obtain a
java_class<type>instance for the type your methods belong to somehow. See Representing Java Classes for various ways to do so. -
Use
java_registrationclass instance to register C++ methods. For the example above you would do something like thisjava_class<jSomething> cls = ...; java_registration<jSomething> registration; registration.add_instance_method("instanceMethod", instanceMethod); registration.add_static_method("staticMethod", staticMethod); registration.perform(env, cls);
Similar to other reasons given in Representing Java Classes it is usually advantageous to perform the registration together with all other Java resolving from within JNI_OnLoad. You can accomplish this by putting the registration code into the constructor of the C++ representation class. The representation class also provides a good scope to put the native implementations in. For the example above
class ClassOfSomething : public java_runtime::simple_java_class<jSomething>
{
ClassOfSomething(JNIEnv * env):
simple_java_class(env)
{
java_registration<jSomething> registration;
registration.add_instance_method("instanceMethod", instanceMethod);
registration.add_static_method("staticMethod", staticMethod);
registration.perform(env, *this);
}
static jboolean instanceMethod(JNIEnv * env, jSomething obj, jint i, jMap m);
static jboolean staticMethod(JNIEnv * env, jclass cls, jint i, jMap m);
};
jboolean ClassOfSomething::instanceMethod(JNIEnv * env, jSomething obj, jint i, jMap m)
{
//implementation
}
jboolean ClassOfSomething::staticMethod(JNIEnv * env, jclass cls, jint i, jMap m)
{
//implementation
}
This library is no longer actively maintained.
For an actively maintained and supported fork please migrate to SimpleJNI at https://github.com/gershnik/SimpleJNI
- Building
-
User's Guide
Declaring Java Types
Accessing Methods and Fields
Representing Java Classes
Implementing Native Methods
Smart References
Error Handling
Obtaining JNIEnv
Initialization
Strings
Arrays
Direct Buffers
Booleans
Sizes -
JniGen Code Generator
Integrating JniGen
Annotations
Processor Options