Calling a Java Method from Native Code
2017-06-05 22:17
393 查看
http://journals.ecs.soton.ac.uk/java/tutorial/native1.1/implementing/method.html
This section illustrates how you can call Java methods from native methods. Our example program,
You can call an instance (non-static) method by following these three steps:
Your native method calls
Your native method then calls
Lastly, your native method calls
The method name is the Java method name in UTF-8 form. Specify the method name for a constructor of a class by enclosing the word
Note that the JNI uses method signatures to denote the type of Java methods. The signature
The following table summarizes the encoding for the Java type signatures:
Java VM Type Signatures
For example, the
whereas the
Array types are indicated by a leading square bracket ([) followed by the type of the array elements.
Using
To eliminate the mistakes in deriving method signatures by hand, you can use the
you can obtain the following output:
The "-s" flag informs
It is important to keep in mind that a method ID is valid only as long as the class from which it is derived is not unloaded. Once the class is unloaded, the method ID becomes invalid. So if you want to cache the method ID, make sure to keep a live reference to the Java class from which the method ID is derived. As long as the reference to the Java class (the
Besides
Obtain the method ID using
Pass the class, method ID, and arguments to the family of static method invocation functions:
If you compare instance method invocation functions to static method invocation functions, you will notice that instance method invocation functions receive the object, rather than the class, as the second argument following the JNIEnv argument. For example, if we add a static method
into
Obtain the method ID from the superclass using
Pass the object, superclass, method Id, and arguments to the family of nonvirtual invocation functions:
It is rare that you will need to invoke the instance methods of a superclass. This facility is similar to calling a superclass method, say
in Java.
Calling Java Methods
This section illustrates how you can call Java methods from native methods. Our example program,
Callbacks.java, invokes a native method. The native method then makes a call back to a Java method. To make things a little more interesting, the Java method again (recursively) calls the native method. This process continues until the recursion is five levels deep, at which time the Java method returns without making any more calls to the native method. To help you see this, the Java method and the native method print a sequence of tracing information.
Calling a Java Method from Native Code
Let us focus on the implementation ofCallbacks_nativeMethod, implemented in
Callbacks.c. This native method contains a call back to the Java method
Callbacks.callback.
JNIEXPORT void JNICALL Java_Callbacks_nativeMethod(JNIEnv *env, jobject obj, jint depth) { jclass cls = (*env)->GetObjectClass(env, obj); jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "(I)V"); if (mid == 0) return; printf("In C, depth = %d, about to enter Java\n", depth); (*env)->CallVoidMethod(env, obj, mid, depth); printf("In C, depth = %d, back from Java\n", depth); }
You can call an instance (non-static) method by following these three steps:
Your native method calls
GetObjectClass. This returns the Java class object to which the Java object belongs.
Your native method then calls
GetMethodID. This performs a lookup for the Java method in a given class. The lookup is based on the name of the method as well as the method signature. If the method does not exist,
GetMethodIDreturns 0. An immediate return from the native method at that point causes a
NoSuchMethodErrorto be thrown in Java code.
Lastly, your native method calls
CallVoidMethod. This invokes an instance method that has
voidreturn type. You pass the object, method ID, and the actual arguments to
CallVoidMethod.
Forming the Method Name and Method Signature
The JNI performs a symbolic lookup based on the method's name and type signature. This ensures that the same native method will work even after new methods have been added to the corresponding Java class.The method name is the Java method name in UTF-8 form. Specify the method name for a constructor of a class by enclosing the word
initwithin angle brackets (this appears as "<init>").
Note that the JNI uses method signatures to denote the type of Java methods. The signature
(I)V, for example, denotes a Java method that takes one argument of type
intand has return type
void. The general form of a method signature argument is:
"(argument-types)return-type"
The following table summarizes the encoding for the Java type signatures:
Java VM Type Signatures
Signature | Java Type |
Z | boolean |
B | byte |
C | char |
S | short |
I | int |
J | long |
F | float |
D | double |
L fully-qualified-class ; | fully-qualified-class |
[ type | type[] |
( arg-types ) ret-type | method type |
Prompt.getLinemethod has the signature:
(Ljava/lang/String;)Ljava/lang/String;
whereas the
Callbacks.mainmethod has the signature:
([Ljava/lang/String;)V
Array types are indicated by a leading square bracket ([) followed by the type of the array elements.
Using javap
to Generate Method Signatures
To eliminate the mistakes in deriving method signatures by hand, you can use the javaptool to print out method signatures. For example, by running:
javap -s -p Prompt
you can obtain the following output:
Compiled from Prompt.java
class Prompt extends java.lang.Object
/* ACC_SUPER bit set */
{
private native getLine (Ljava/lang/String;)Ljava/lang/String;public static main ([Ljava/lang/String;)V<init> ()V
static <clinit> ()V
}
The "-s" flag informs
javapto output signatures rather than normal Java types. The "-p" flag causes private members to be included.
Calling Java Methods Using Method IDs
In JNI, you pass the method ID to the actual method invocation function. This makes it possible to first obtain the method ID, which is a relatively expensive operation, and then use the method ID many times at later points to invoke the same method.It is important to keep in mind that a method ID is valid only as long as the class from which it is derived is not unloaded. Once the class is unloaded, the method ID becomes invalid. So if you want to cache the method ID, make sure to keep a live reference to the Java class from which the method ID is derived. As long as the reference to the Java class (the
jclassvalue) exists, the native code keeps a live reference to the class. The section Local and Global References explains how to keep a live reference even after the native method returns and the
jclassvalue goes out of scope.
Passing Arguments to Java Methods
The JNI provides several ways to pass arguments to a Java method. Most often, you pass the arguments following the method ID. There are also two variations of method invocation functions that take arguments in an alternative format. For example, theCallVoidMethodVfunction receives the arguments in a
va_list, and the
CallVoidMethodAfunction expects the arguments in an array of
jvalueunion types:
typedef union jvalue { jboolean z; jbyte b; jchar c; jshort s; jint i; jlong j; jfloat f; jdouble d; jobject l; } jvalue;
Besides
CallVoidMethodfunction, the JNI also supports instance method invocation functions with other return types, such as
CallBooleanMethod,
CallIntMethod, and so on. The return type of the method invocation function must match with the Java method you wish to invoke.
Calling Static Methods
You can call static Java method from your native code by following these steps:Obtain the method ID using
GetStaticMethodID, as opposed to
GetMethodID.
Pass the class, method ID, and arguments to the family of static method invocation functions:
CallStaticVoidMethod,
CallStaticBooleanMethod, and so on.
If you compare instance method invocation functions to static method invocation functions, you will notice that instance method invocation functions receive the object, rather than the class, as the second argument following the JNIEnv argument. For example, if we add a static method
static int incDepth(int depth) {return depth + 1};
into
Callback.java, we can call it from
Java_Callback_nativeMethodusing:
JNIEXPORT void JNICALL Java_Callbacks_nativeMethod(JNIEnv *env, jobject obj, jint depth) { jclass cls = (*env)->GetObjectClass(env, obj); jmethodID mid = (*env)->GetStaticMethodID(env, cls, "incDepth", "(I)I"); if (mid == 0) return; depth = (*env)->CallStaticIntMethod(env, cls, mid, depth);
Calling Instance Methods of a Superclass
You can call instance methods defined in a superclass that have been overridden in the class to which the object belongs. The JNI provides a set ofCallNonvirtual<type>Methodfunctions for this purpose. To call instance methods from the superclass that defined them, you do the following:
Obtain the method ID from the superclass using
GetMethodID, as opposed to
GetStaticMethodID).
Pass the object, superclass, method Id, and arguments to the family of nonvirtual invocation functions:
CallNonvirtualVoidMethod,
CallNonvirtualBooleanMethod, and so on.
It is rare that you will need to invoke the instance methods of a superclass. This facility is similar to calling a superclass method, say
f, using:
super.f();
in Java.
相关文章推荐
- Considerations when calling Java from PeopleCode
- http://stuf.ro/calling-c-code-from-java-using-jni
- java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class
- java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class
- Creating a Java VM from Android Native Code
- How to call a android/native service from a native/android (java) code
- Qt 5.4/Android: Call Qt method from Java code
- Performing native commands in java code
- Performing native commands in java code
- 《Head First Java》And《Beginning Java Objects: From Concepts To Code, Second Edition》
- Compiling and Running a Java Program with a Native Method
- Java Compile Error: The code of method is exceeding the 65535 bytes limit
- a example for calling java code in javascript use dwr
- Calling App Engine from PeopleCode
- Beginning Java Objects: From Concepts To Code, Second Edition
- java.lang.IllegalAccessError: tried to access method net.sf.ehcache.CacheManager.()V from class org.hibernate.cache.EhCa
- java native method
- Calling an Application Engine from PeopleCode
- java Native Method初涉
- java Native Method