Through the first article, we understand that before calling the native method, The first thing to call the System.loadlibrary interface is to load a dynamic library that implements the native method for normal access, otherwise it throws a Java.lang.UnsatisfiedLinkError exception and cannot find the prompt for the XX method. Now let's think about how the JVM can correctly find the native function in a dynamic library that is implemented in C/s, by invoking a native method in Java .
There are two ways in which the JVM looks for native methods:
1> naming rules According to the JNI specification
2> invokes the Registernatives function provided by JNI to register the local function with the JVM. (Details will be introduced later)
This article passes the first article in the HelloWorld example Java_com_study_jnilearn_helloworld_sayhello function to describe the first way in detail:
/* Don't EDIT this file-it are machine generated */#include <jni.h>/* Header for class Com_study_jnilearn_hellowor LD */#ifndef _included_com_study_jnilearn_helloworld#define _included_com_study_jnilearn_helloworld#ifdef __ Cplusplusextern "C" {#endif */* Class: com_study_jnilearn_helloworld * Method: SayHello * Signature: (ljava/ lang/string;) ljava/lang/string; */jniexport jstring jnicall Java_com_study_jnilearn_helloworld_sayhello (jnienv *, Jclass, jstring); #ifdef __ Cplusplus} #endif #endif
The role of Jniexport and Jnicall:
In the previous article, when we compiled HELLOWORLD.C into a dynamic library, we included the two header directories in the JDK installation directory with the-I parameter:
Gcc-dynamiclib-o/users/yangxin/library/java/extensions/libhelloworld.jnilib jni/helloworld.c-framework javavm-i/ $JAVA _home/include-i/$JAVA _home/include/darwin
The first directory is the jni.h header file directory, the second is the cross-platform header file directory (Mac OS X system directory named Darwin, under Windows directory named Win32,linux under the directory named Linux), used to define platform-related macros,
two macros used to identify the purpose of a function
jniexport and jnicall, defined in the Darwin directory jni_md.h
the header file . compiling DLL dynamic libraries in Windows stipulates that if a function in a dynamic library is to be called externally, it needs to be added in the function declarationan __declspec (dllexport) identity that indicates that the function is exported externally and can be called. In the Linux/unix system, these two macros can be omitted without adding. The difference between the two platforms is due to the different executable file formats produced by the respective compilers. Here is an article detailing the two platform-compiled dynamic library differences: http://www.cnblogs.com/chio/archive/2008/11/13/1333119.html. The Jnicall value in Windows is __stdcall, which is used to constrain the rules of the function into the stack order and stack cleanup.
jni_md.h Header file contents under Windows:
Linux under Jni_md.h header file content:
#ifndef _javasoft_jni_md_h_#define _javasoft_jni_md_h_#define jniexport#define jniimport#define JNICALLtypedef int Jint; #ifdef _LP64/* 64-bit Solaris */typedef long jlong; #elsetypedef long long Jlong; #endiftypedef signed char Jbyte; #end If
As can be seen from the Jni_md.h header file under Linux, Jniexport and jnicall are an empty definition, so the JNI function declaration under Linux can omit both macros.
Naming rules for functions:
using the Javah tool to generate the function prototype header file, the function naming rule is: Java_ class Full Path _ method name. such as Java_com_study_jnilearn_helloworld_sayhello, where Java_ is a function prefix, Com_study_jnilearn_helloworld is the class name, SayHello are method names, which are concatenated with _ ( underscore) .
Function parameters:
Jniexport jstring jnicall Java_com_study_jnilearn_helloworld_sayhello (jnienv *, Jclass, jstring);
The first parameter: jnienv* is the first parameter that defines any native function (including the function registered by the Registernatives function that calls JNI), which accesses the JNI function table pointer for the JVM data structure
The second argument: Call the instance of the native method in Java or the class object, if the native method is an instance method, the parameter is Jobject, and if it is a static method, it is Jclass
The third parameter: Java corresponds to the data type in Jni, and the string type in Java corresponds to the jstring type of JNI. (The mapping between Java and JNI data types is described in detail later)
function return value type:
Jstring in the middle of the Jniexport and Jnicall macros, representing the type of return value of the function, corresponding to the Java string type
Summary:
When we are familiar with the native function naming rules of JNI, we can not use the Javah command to generate the function prototype of the corresponding Java native method, just write the corresponding function prototype and implement according to the function naming rules.
For example, the Com.study.jni.Utils class also has a native instance method that calculates the addition, with two int parameters and an int return value: public native int Add (int num1, int num2), The function prototype corresponding to JNI is: Jniexport jint jnicall java_com_study_jni_utils_add (jnienv *, Jobject, jint,jint);
JNI/NDK Development Guide (ii)--JVM rules for finding Java native methods