Android JNI call description

Source: Internet
Author: User
Tags case statement

Disclaimer: you are welcome to repost. Please indicate the source when reprinting!

Http://blog.csdn.net/flydream0/article/details/7371692

1. Overview

JNI is the abbreviation of Java Native Interface. Java Native Interface (JNI) standards have become part of the Java platform since java1.1. It allows Java code to interact with code written in other languages. JNI was initially designed for locally compiled languages, especially C and C ++, but it does not prevent you from using other languages, as long as the call conventions are supported.

Because the classes at the Android Application layer are written in Java, after these Java classes are compiled into Dex-type bytecode, they must be run on the Dalvik virtual machine, the Dalvik virtual machine plays an important role in Android. android middleware is written by C/C ++. The components written by C/C ++ are not running on the Dalvik virtual machine. So how does Java code at the application layer communicate with components written in C/C ++?

2. Load the. So file

System. loadlibrary (*. So file );

In Java code, you can use loadlibrary to require the VM to load the so file. The Java code is generally in the following form:

public class jnitest {    static {        System.loadLibrary("jnitest");    }    //...}

When the above Code is run, libjnitest will be searched in the/system/lib/directory. so file, will be loaded into the VM, so that the Java code and the C component constitute a connection, then you can use some methods to call each other.

3 jni_onload and jni_onunload

In Android, when the program runs system on the Java layer. loadlibrary ("jnitest"); after this line of code, the program will load libjnitest. so file. At the same time, a "LOAD" event is generated. After this event is triggered, the program is loaded by default. find and execute the jni_onload function in the function list of the so file, which is opposite to the "LOAD" event and is loaded. when the so file is uninstalled, the "Unload" event is triggered. At this time, the program will be loaded by default. find and execute the jni_onunload function in the function list of the so file, and then uninstall it. so file. Note that the jni_onload and jni_onunload functions are in. the so component is not mandatory, and users can not implement it. Java code can call functions in the C component, as described in the following sections.

The reason for implementing these two functions (especially the jni_onload function) in the C component is often an initialization or "aftercare" work. We can think of jni_onload. the so component's initialization function is executed when it is loaded for the first time (the DLL file under the window can also be similar to the Mechanism, in the _ dll_main () function, A swith case statement is used to identify whether to load or detach data ). The jni_onunload function is called when it is detached.

From this point of view, it is not difficult to understand why many jni c components implement the jni_onload function. Generally, the jni_onload function in the C component is used to register interfaces for the VM, so that the VM can quickly find the C function to be called by Java code. (In addition, the jni_onload function has another function, that is, to tell the VM that the C component uses the JNI version. If the jni_onload function is not implemented, the default function is JNI 1.1 ).

4. The native method 4.1 is used for explicit registration:

The Java class at the application layer calls the native function through the VM. Generally, native functions in *. So are searched through VM. If you need to call multiple times in a row, it will take a lot of time to search for them each time. At this time, the C component developer can register the local function with the VM, so as to speed up the subsequent call of native functions. as you can imagine, assume that there is a native function linked list in the VM, Which is empty at the beginning. The native function linked list is empty before explicit registration, before Java calls the native function, it first searches for the native function to be called in this linked list. If it is found, it is used directly. If it is not found, it must be loaded. the function list in the so file is searched. Every time Java calls the native function, this process is performed. Therefore, the efficiency will naturally decrease. To overcome this problem, we can. when the so file is loaded and initialized, that is, in the jni_onload function, the native function is first registered to the native function linked list of the VM, every time Java calls the native function in the future, it will find the corresponding function in the native function linked list in the VM to speed up.

Note: In the android source code development environment, the native method is registered explicitly.

4.2 In the android source code development mode, there are two ways to display and register native Methods: Method 1: Use the jniregisternativemethods defined in the jnihelp. h header file.

For example ~ /Working_directory/frameworks/base/services/JNI/com_android_server_location_gpslocationprovider.cpp:

Note: most other CPP files in the same directory of this file use this method for explicit native registration.

static JNINativeMethod sMethods[] = {     /* name, signature, funcPtr */    {"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native},    {"native_is_supported", "()Z", (void*)android_location_GpsLocationProvider_is_supported},    {"native_init", "()Z", (void*)android_location_GpsLocationProvider_init},    {"native_cleanup", "()V", (void*)android_location_GpsLocationProvider_cleanup},    {"native_set_position_mode", "(IIIII)Z", (void*)android_location_GpsLocationProvider_set_position_mode},    {"native_start", "()Z", (void*)android_location_GpsLocationProvider_start},    {"native_stop", "()Z", (void*)android_location_GpsLocationProvider_stop},    {"native_delete_aiding_data", "(I)V", (void*)android_location_GpsLocationProvider_delete_aiding_data},    {"native_read_sv_status", "([I[F[F[F[I)I", (void*)android_location_GpsLocationProvider_read_sv_status},    {"native_read_nmea", "([BI)I", (void*)android_location_GpsLocationProvider_read_nmea},    {"native_inject_time", "(JJI)V", (void*)android_location_GpsLocationProvider_inject_time},    {"native_inject_location", "(DDF)V", (void*)android_location_GpsLocationProvider_inject_location},    {"native_supports_xtra", "()Z", (void*)android_location_GpsLocationProvider_supports_xtra},    {"native_inject_xtra_data", "([BI)V", (void*)android_location_GpsLocationProvider_inject_xtra_data},    {"native_agps_data_conn_open", "(Ljava/lang/String;)V", (void*)android_location_GpsLocationProvider_agps_data_conn_open},    {"native_agps_data_conn_closed", "()V", (void*)android_location_GpsLocationProvider_agps_data_conn_closed},    {"native_agps_data_conn_failed", "()V", (void*)android_location_GpsLocationProvider_agps_data_conn_failed},    {"native_agps_set_id","(ILjava/lang/String;)V",(void*)android_location_GpsLocationProvider_agps_set_id},    {"native_agps_set_ref_location_cellid","(IIIII)V",(void*)android_location_GpsLocationProvider_agps_set_reference_location_cellid},    {"native_set_agps_server", "(ILjava/lang/String;I)V", (void*)android_location_GpsLocationProvider_set_agps_server},    {"native_send_ni_response", "(II)V", (void*)android_location_GpsLocationProvider_send_ni_response},    {"native_agps_ni_message", "([BI)V", (void *)android_location_GpsLocationProvider_agps_send_ni_message},    {"native_get_internal_state", "()Ljava/lang/String;", (void*)android_location_GpsLocationProvider_get_internal_state},    {"native_update_network_state", "(ZIZZLjava/lang/String;Ljava/lang/String;)V", (void*)android_location_GpsLocationProvider_update_network_state },};int register_android_server_location_GpsLocationProvider(JNIEnv* env){    return jniRegisterNativeMethods(env, "com/android/server/location/GpsLocationProvider", sMethods, NELEM(sMethods));}

Here, both jniregisternativemethods and nelem are defined in the header file jnihelp. h:

#include "JNIHelp.h"

Add the following to the Android. mk file:

LOCAL_SHARED_LIBRARIES +=libnativehelper 

Method 2: Use androidruntime: registernativemethods

For example ~ /Working_directory/frameworks/base/Media/JNI/android_media_mediaplayer.cpp:

Note: most other CPP files in the current directory use this method for explicit native registration.

static JNINativeMethod gMethods[] = {    {"setDataSource",       "(Ljava/lang/String;)V",            (void *)android_media_MediaPlayer_setDataSource},    {        "_setDataSource",        "(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V",        (void *)android_media_MediaPlayer_setDataSourceAndHeaders    },    {"setDataSource",       "(Ljava/io/FileDescriptor;JJ)V",    (void *)android_media_MediaPlayer_setDataSourceFD},    {"_setVideoSurface",    "(Landroid/view/Surface;)V",        (void *)android_media_MediaPlayer_setVideoSurface},    {"prepare",             "()V",                              (void *)android_media_MediaPlayer_prepare},    {"prepareAsync",        "()V",                              (void *)android_media_MediaPlayer_prepareAsync},    {"_start",              "()V",                              (void *)android_media_MediaPlayer_start},    {"_stop",               "()V",                              (void *)android_media_MediaPlayer_stop},    {"getVideoWidth",       "()I",                              (void *)android_media_MediaPlayer_getVideoWidth},    {"getVideoHeight",      "()I",                              (void *)android_media_MediaPlayer_getVideoHeight},    {"seekTo",              "(I)V",                             (void *)android_media_MediaPlayer_seekTo},    //...}// This function only registers the native methodsstatic int register_android_media_MediaPlayer(JNIEnv *env){    return AndroidRuntime::registerNativeMethods(env,                "android/media/MediaPlayer", gMethods, NELEM(gMethods));}

Specifically, androidruntime: registernativemethods is defined in the header file android_runtime/androidruntime. H. It is used in:

#include "android_runtime/AndroidRuntime.h"

You must add the following to the Android. mk file:

LOCAL_SHARED_LIBRARIES += \    libandroid_runtime 

For more information about function naming, see the blog article: how to provide an interface summary through the JNI method in Android.

Note: The above two native registration methods are only applicable to the android source code development environment. As for how to explicitly register the native method in the android ndk environment, we have not studied them yet, these two methods are not currently supported by ndk. In the ndk development mode, native functions are generally registered implicitly, which is the content to be discussed later.

5. Register the native method implicitly.

As mentioned in the previous section 3rd, the jni_onload and jni_onunload functions do not require implementation. In this case, they are equivalent to loading. in the so file, there is no initialization function. Since there is no initialization function, it is impossible to explicitly register the native method. At this time, how can we make the Java code at the application layer call the lower-layer C functions?

Fortunately, even if we do not use any code for native explicit registration, the Java code at the application layer will use the default method when calling the native function. find the corresponding native function in the function list in the so file, except that this native function has a default correspondence with the native function name declared in Java. For example:

Native member function of Java class: Public native int socket_send (INT Region ID, string ARGUS. find the jint jnicall java_com_hase_bclm_bclm_socket_1send (jnienv * ENV, jobject OBJ, jint Region ID, jstring ARGUS) in the function list in the so file, the VM automatically registers the native function to the native function linked list in the VM to accelerate subsequent calls of the same JNI.

But the next question is, how do we know that the Java Native member function corresponds to the native function name in the C component? Simply using the function name may be something we can do, but it is dumb to make it more complicated. Fortunately, JDK provides a javah tool that can be used to automatically generate C component header files through the. Class file.

For example, you write a XXX in Java. java file. Some native member functions are declared in the Java type. This XXX. after the Java file is compiled, XXX is generated. class file. enter the command line in the directory where the class package is located:

$javah -jni com.packagename.yourclassname

A header file is generated in the current directory.

For example:

Javah-JNI com. Test. Example

The com_test_example.h header file is generated in the current directory.

The com structure in the current directory is com/test/example. Class.

Copy the header file to your C component project to implement the declared native function.

Previously, it has been explained in the relevant chapter about explicitly registering native functions. Explicit registration adds native functions to the native function linked list in the VM to accelerate the efficiency of subsequent JNI calls, in fact, during implicit native registration, every time a JNI call is executed, the VM. after finding the corresponding native function in the so function list, it will also be registered to the native function linked list in the VM, in addition to the first execution of a JNI call, the method of implicit native registration will be slightly slower. Subsequent calls will directly find the corresponding native function in the native function linked list in the VM, in this case, the efficiency of explicit and implicit native registration is almost the same.

OK. This is the end!

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.