Analysis of Android JNI (1)

Source: Internet
Author: User

JNI is short for Java Native Interface, and JNI is a mechanism. With JNI, you can call other native code in a Java program or make native code call the code at the Java layer. That is to say, with JNI, we can make the Java and native layers in the android project develop strengths and cooperate with each other. Shows the position of JNI in Android.



Well, who doesn't know that JNI should be in the middle of Java and native?


Compared with the native layer, JNI is an interface. To access the native layer, Java-layer programs must use JNI. Let's look at several questions.

1. How do I tell the VM (Virtual Machine) Java layer which libs need to call the native layer?

We know that Java programs run on VMS, whereas libs on the native layer do not. To enable the Java layer to access the Libs of the native layer, you must tell the VM which native layer libs to use. See the following code.

[Java]
View plaincopy
  1. Public class mediaplayer
  2. {
  3. ...
  4. Static {
  5. System. loadlibrary ("media_jni ");
  6. Native_init ();
  7. }
  8. ...
  9. Private native final void native_setup (Object mediaplayer_this );
  10. ...
  11. }

We can see that the above Code contains a piece of code surrounded by static blocks in the mediaplayer class, where system. loadlibrary ("media_jni") tells VM to load the dynamic library libmedia_jni.so. When will this dynamic library be loaded? Because of the static statement block, mediaplayer is loaded when it is first instantiated. In this Code, we also see a function native_init (), which is declared as native, that is, to tell VM that the function is implemented by the native layer.

2. How to map the Java layer to the native layer.

In fact, what I want to express is how to map the Java-layer code to the native-Layer Code. For example, the above Code contains a native function native_init (), so how can we map this function to a specific function implemented by C/C ++ (or other languages? PS: This cainiao lacks expression skills. I don't know if you can understand it.

When the VM runs to system. when loadlibrary () is used, the jni_onload (JavaVM * Vm, void * Reserved) function in native libs will be executed, because the jni_onload function is the first method called to enter the native layer from the Java layer, therefore, you can initialize some native layer components in the jni_onload function. More importantly
The native method of the Java layer will be registered in the jni_onload (JavaVM * Vm, void * Reserved) function. See the following code:

[Java]
View plaincopy
  1. Jint jni_onload (JavaVM * Vm, void * Reserved)
  2. {
  3. Jnienv * Env = NULL;
  4. Jint result =-1;
  5. // Determine the JNI version
  6. If (Vm-> getenv (void **) & ENV, jni_version_1_4 )! = Jni_ OK ){
  7. LOGE ("ERROR: GetEnv failed \ n ");
  8. Goto bail;
  9. }
  10. Assert (env! = NULL );
  11. If (register_android_media_MediaPlayer (env) <0 ){
  12. LOGE ("ERROR: MediaPlayer native regiled failed \ n ");
  13. Goto bail;
  14. }
  15. If (register_android_media_MediaRecorder (env) <0 ){
  16. LogE ("error: mediarecorder native regiled failed \ n ");
  17. Goto bail;
  18. }
  19. If (register <span style = "font-size: 16px;"> _ android_media_mediascanner (ENV) <0 ){
  20. LogE ("error: mediascanner native regiled failed \ n ");
  21. Goto bail;
  22. } </Span>
  23. If (register_android_media_mediametadataretriever (ENV) <0 ){
  24. LOGE ("ERROR: MediaMetadataRetriever native regiled failed \ n ");
  25. Goto bail;
  26. }
  27. If (register_android_media_AmrInputStream (env) <0 ){
  28. LOGE ("ERROR: AmrInputStream native regiled failed \ n ");
  29. Goto bail;
  30. }
  31. If (register_android_media_ResampleInputStream (env) <0 ){
  32. LOGE ("ERROR: ResampleInputStream native regiled failed \ n ");
  33. Goto bail;
  34. }
  35. If (register_android_media_MediaProfiles (env) <0 ){
  36. LOGE ("ERROR: MediaProfiles native regiled failed ");
  37. Goto bail;
  38. }
  39. /* Success -- return valid version number */
  40. Result = JNI_VERSION_1_4;
  41. Bail:
  42. Return result;
  43. }

The JNI_OnLoad (JavaVM * vm, void * reserved) function of the above Code is implemented in the libmedia_jni.so library. The above code calls some functions, such as register_android_media_MediaPlayer (env). These functions are used to register native methods. Let's take a look at the implementation of the register_android_media_MediaPlayer (env) function.

[Java]
View plaincopy
  1. // This function only registers the native methods
  2. Static int register_android_media_MediaPlayer (JNIEnv * env)
  3. {
  4. Return AndroidRuntime: registerNativeMethods (env,
  5. "Android/media/MediaPlayer", gMethods, NELEM (gMethods ));
[Java]
View plaincopy
  1. /*
  2. * Register native methods using JNI.
  3. */
  4. /* Static */int AndroidRuntime: registerNativeMethods (JNIEnv * env,
  5. Const char * className, const JNINativeMethod * gMethods, int numMethods)
  6. {
  7. Return jniRegisterNativeMethods (env, className, gMethods, numMethods );
  8. }

The jniRegisterNativeMethods function completes the ing of java standard native functions. Next, let's take a look at the meanings of the parameters in the above function.

A, JNIEnv * env. I found the following information about JNIEnv on google:

JNI defines two key data structures, "JavaVM" and "JNIEnv ". both of these are essential tiallypointers to pointers to function tables. (In the C ++ version, they're classes with apointer to a function table and a member function for each JNI function that indirects
Throughthe table.) The JavaVM provides the "invocation interface" functions, which allow you to create and destroy a JavaVM. In theory you can have multiple JavaVMs per process, but Android only allows one.

The jnienv provides most of the JNI functions. Your native functions all receive a jnienv asthe first argument.

The jnienv is used for thread-local storage. For this reason,You cannot share a JNIEnv between threads. If a piece of code has no other way to get its jnienv, you shocould sharethe JavaVM, and useGetEnvTo discover the thread's
Jnienv. (assuming it has one; seeAttachCurrentThreadBelow .)

Note that jnienv is a local variable of a thread, which indicates that jnienv exists in a multi-threaded environment, because VM is usually multi-threading). When jni_onload () is called by each thread, the passed jnienv metric values are different. To work with this multi-execution environment, C/C ++ component developers can avoid conflicts in execution threads by using different jnienv metric values when writing local functions, in order to ensure that the written local functions can be safely executed in the android multi-thread VM. For this reason, when
When calling a function of the C/C ++ component, the jnienv indicator value is passed to it.

B, char * classname. There is nothing to say about it. The class name in the Java space contains the package name.

C, jninativemethod * gmethods, which is passed in as a gmethods pointer of the jninativemethod type. gmethods points to a jninativemethod array. Let's first look at the structure jninativemethod.

[Java]
View plaincopy
  1. Typedef struct {
  2. Const char * name;/* name of the function in Java */
  3. Const char * signature;/* describes the function parameters and return values */
  4. Void * fnPtr;/* function pointer, pointing to C function */
  5. } JNINativeMethod;

Let's take a look at the gmethods array.

[Java]
View plaincopy
  1. Static JNINativeMethod gMethods [] = {
  2. {"SetDataSource", "(Ljava/lang/String;) V", (void *) android_media_MediaPlayer_setDataSource },
  3. ...
  4. {"Setaux?tsendlevel", "(F) V", (void *) android_media_mediaplayer_setaux=tsendlevel },
  5. {"AttachAuxEffect", "(I) V", (void *) android_media_MediaPlayer_attachAuxEffect },
  6. {"Getorgandbindex", "(ii) I", (void *) android_media_mediaplayer_getorgandbindex },
  7. };

D, int nummethods, not explained.


This completes the ing from the Java Native function to the JNI layer function. Of course, the specific function implementation is still implemented by the JNI layer function to call the C/C ++ function.

----------------------------------------- The general process of JNI is explained here. The details of JNI will be explained next time. This cainiao has limited capabilities. please correct me if there is any error in the blog. Thank you.

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.