When you get the field ID and the method ID , you need to do a search with the field, the name of the method, and the descriptor. The retrieval process is relatively time-consuming, so this section discusses using caching techniques to reduce the cost of this process. There are two main ways to cache field IDs and method IDs . The two differences are primarily in the time at which the cache occurs, when the field ID and method ID are used, or when static initialization of a class is defined for the field and method.
1. Cache when used
The field ID and method ID can be cached when the value of the field is accessed or when the method is called back. The following code stores the field ID in a static variable so that when the local method is called repeatedly, you do not have to re-search the field ID.
jniexport void Jnicall Java_instancefieldaccess_accessfield (jnienv *env, Jobject obj) { static Jfieldid fid_s = NULL; /* Cached field ID for S */ Jclass CLS = (*env)->getobjectclass (env, obj); Jstring Jstr; const char *STR; if (fid_s = = NULL) { fid_s = (*env)->getfieldid (env, CLS, "s", "ljava/lang/string;"); if (fid_s = = NULL) { return;/* Exception already thrown * /}} printf ("in c:\n"); Jstr = (*env)->getobjectfield (env, obj, fid_s); str = (*env)->getstringutfchars (env, JSTR, NULL); if (str = = NULL) { return;/* out of Memory * /} printf (" c.s = \"%s\ "\ n", str); (*env)->releasestringutfchars (env, JSTR, str); Jstr = (*env)->newstringutf (env, "123"); if (jstr = = NULL) { return;/* out of Memory * /} (*ENV)->setobjectfield (env, obj, fid_s, jstr);}
2. Initializing the cache
In many cases, it is convenient to initialize the field ID and the method ID before it is used. The VM performs the static initialization of the class before invoking the methods and fields of a class, so it is a good idea to compute and cache the field ID and method ID during static initialization of the class.
For example, in order to cache the Instancemethodcall.callback method ID, we introduced a new local method, Initids, which was called during the static initialization of Instancemethodcall.
/** * Cache ID */jmethodid callbackstatic; Jniexport void Jnicall java_com_example_jniandroid_service_cfunction_calljninative2 (JNIENV * env, Jobject obj) {LOGI (" Cached ID ... ");(*env)->callstaticvoidmethod (env, obj, callbackstatic);} Jniexport void Jnicall java_com_example_jniandroid_service_cfunction_initids (jnienv * env, Jobject obj) {// Call the static method Jclass CLS = (*env)->getobjectclass (env, obj), callbackstatic = (*env)->getstaticmethodid (env, CLS, " Callbackstatic "," () V ");}
The comparison between the two ways to cache IDs
If the JNI programmer does not control the source code of the class in which the method and field resides, caching is a reasonable option when it is used. For example, in mynewstring, we cannot insert a Initids method in the String class.
There are some drawbacks to using the cache compared to a static initial-time cache:
1, when using the cache, each use should be checked.
2. The method ID and field ID are invalidated when the class is unload, and if you cache the ID when you use it, you must make sure that the class is not unload as long as the local code depends on the value of the ID (the next chapter demonstrates how to prevent the class from being unload by creating a class reference using the JNI function). On the other hand, if the cache occurs at static initialization, the ID is recalculated when the class is unload and reload.
Therefore, the field ID and method ID are cached whenever possible at static initialization.
JNI _8_jni Cache fields and method IDs