- (Object) Instance methods must be invoked on a specific instance of a class.
- (Class) Static methods may be invoked independent of any instance.
- Calling Instance Methods (Example) InstanceMethodCall.java: a native method that in turn calls an instance method implemented in the Java programming language.
- InstanceMethodCall.java
- Generate C header file: InstanceMethodCall.h
- C implementation of InstanceMethodCall.c
- GetMethodID performs a lookup for the method in the given class. The lookup is based on the name and type descriptor of the method. If the method does not exist, GetMethodID returns NULL and causes a NoSuchMethodError to be thrown in the code.
- CallVoidMethod invokes an instance method that has the return type void. You pass the object, the method ID, and the actual arguments to CallVoidMethod.
- Generate the shared library file - libInstanceMethodCall.so
- RUN InstanceMethodCall output:
class InstanceMethodCall { private native void nativeMethod(); private void callback() { System.out.println("Output: In Java code"); } public static void main(String args[]) { InstanceMethodCall c = new InstanceMethodCall(); c.nativeMethod(); } static { System.loadLibrary("InstanceMethodCall"); } }
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class InstanceMethodCall */ #ifndef _Included_InstanceMethodCall #define _Included_InstanceMethodCall #ifdef __cplusplus extern "C" { #endif /* * Class: InstanceMethodCall * Method: nativeMethod * Signature: ()V */ JNIEXPORT void JNICALL Java_InstanceMethodCall_nativeMethod (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
#include <stdio.h> #include <jni.h> JNIEXPORT void JNICALL Java_InstanceMethodCall_nativeMethod(JNIEnv *env, jobject obj) { jclass cls = (*env)->GetObjectClass(env, obj); jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "()V"); if (mid == NULL) { return; /* method not found */ } printf("Output: In C code\n"); (*env)->CallVoidMethod(env, obj, mid); }
- Two steps required to call an instance method:
gcc -shared -I/usr/local/jdk1.6.20_21/include -I/usr/local/jdk1.6.20_21/include/linux InstanceMethodCall.c -o libInstanceMethodCall.so
Output: In C code
Output: In Java code
- Calling Static Methods Similarly, we can perform callbacks to static methods from native code by following steps:
- Obtain the method ID using GetStaticMethodID, as opposed to GetMethodID.
- Pass the class, method ID, and arguments to one of the family of static method invocation functions: CallStaticVoidMethod, CallStaticBooleanMethod, and so on.
- StaticMethodCall.java
- Generate C header file: StaticMethodCall.h
- C implementation of StaticMethodCall.c
- Generate the shared library file - libStaticMethodCall.so
- RUN StaticmethodCall output:
- (Example) StaticMethodCall.java: a slight variation of the earlier InstanceMethodCall example
class StaticMethodCall { private native void nativeMethod(); private static void callback() { System.out.println("Output: In Java code"); } public static void main(String args[]) { StaticMethodCall c = new StaticMethodCall(); c.nativeMethod(); } static { System.loadLibrary("StaticMethodCall"); } }
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class StaticMethodCall */ #ifndef _Included_StaticMethodCall #define _Included_StaticMethodCall #ifdef __cplusplus extern "C" { #endif /* * Class: StaticMethodCall * Method: nativeMethod * Signature: ()V */ JNIEXPORT void JNICALL Java_StaticMethodCall_nativeMethod (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
#include <stdio.h> #include <jni.h> JNIEXPORT void JNICALL Java_StaticMethodCall_nativeMethod(JNIEnv *env, jobject obj) { jclass cls = (*env)->GetObjectClass(env, obj); jmethodID mid = (*env)->GetStaticMethodID(env, cls, "callback", "()V"); if (mid == NULL) { return; /* method not found */ } printf("Output: In C code\n"); (*env)->CallStaticVoidMethod(env, cls, mid); }
gcc -shared -I/usr/local/jdk1.6.20_21/include -I/usr/local/jdk1.6.20_21/include/linux StaticMethodCall.c -o libStaticMethodCall.so
Output: In C code
Output: In Java code
- JNI Method Descriptors
- similar to how descriptor denotes field types
- Format:('[' + ARGUMENT_TYPE) + RETURN_TYPE For example:
native private String getLine(String);
"(Ljava/lang/String;)Ljava/lang/String;"
public static void main(String[] args);
"([Ljava/lang/String;)V"
For example: javap -s -p InstanceMethodCall
-s: to output JNI descriptor strings rather than types as they appear in the Java programming language
-p: to include information about the private members of the class
The output:
Compiled from "InstanceMethodCall.java"
class InstanceMethodCall extends java.lang.Object{
InstanceMethodCall();
Signature: ()V
private native void nativeMethod();
Signature: ()V
private void callback();
Signature: ()V
public static void main(java.lang.String[]);
Signature: ([Ljava/lang/String;)V
static {};
Signature: ()V }
0 意見:
張貼留言