Yesterday, I wrote about the basic composition and function of JNI. Continue to refine the following sections today
0: About instance references and class references (questions left yesterday about the second parameter)
In fact, this kind of think too much. Today, I've written two different native methods.
Demo.java
Class Demo { //slightly ... private static native void Staticmethod (String userinput);//static method private native void Instacemethod ();//Instance method
public static void Main (String args[]) {//Omit ...}}
corresponding to the compiled header file is this
Slightly... jniexport void Jnicall Java_demo_staticmethod (jnienv *, Jclass, jstring);
//...
jniexport void Jnicall Java_demo_instacemethod (jnienv *, jobject);//slightly ...
Some simple examples do not use Jclass, but once a static method is used to manipulate something, it uses the Jclass class reference. The difference between them is actually here.
1:jni's argument
In the previous article it has mentioned that the Java Layer object is passed to the JNI layer. It is through a C pointer type that points to the internal structure of the Java VM, so you must not manipulate the pointer directly by bypassing the JNI intrinsic function for efficiency or convenience. The first two parameters in JNI are also described in the previous article, and if it involves passing parameters within the native method, then the third parameter is involved. For example, if you need to pass a string, the third argument will be jstring. The jstring here is a type. In JNI, the data types are basically the same, with J in front of the original data types that you are familiar with. For example, the int type is Jint, and the Boolean is Jboolean. The corresponding method is also readily applicable, I believe the old-timers have already perfected it well. And now the IDE is so powerful (I'm currently using sublime to write Java, command-line compilation, not to mention other Ides), plus the network. It's more natural to be familiar with it. Here is a small example to introduce.
1.1 String
Look at the Java code First:
Prompt.java
Class Prompt {static {system.loadlibrary ("Prompt");//Prompt to load name Prompt.dll library}private native String GetLine (string Prompt) ;//Declaration native method public static void Main (String argv[]) {Prompt p = new Prompt (); string input = P.getline ("Type a Line:");//string as parameter System.out.println ("User typed:" + input);}}
Prompt.c
#define _crt_secure_no_warnings#include <stdio.h> #include <jni.h> #include "Prompt.h" Jniexport jstring Jnicall Java_prompt_getline (jnienv *env, Jobject obj, jstring Prompt) {char buf[128];const jbyte *str;//Converts a string to Utf-8str = (*env)->getstringutfchars (env, prompt, null); if (str = = null) {return null;} printf ("%s", str);//Release conversion memory (*ENV)->releasestringutfchars (env, prompt, str) scanf ("%s", buf);// Constructs a new string return (*ENV)->newstringutf (env, BUF);}
If you print printf directly ("%s", prompt), jstring and char* are different types. The char*,jni that need to be converted to C can be recognized to support Unicode/utf-8 character encoding for mutual transfer. Here are a few ways to remember that string manipulation is very common oh. Here, remember to call Releasestringutfchars to release the allocated memory in the Getstringutfchars. where "str = (*env)->getstringutfchars (env, prompt, NULL);" The third parameter in the prototype is Jboolean *. A copy is returned for Jni_true, which is generally set to NULL when not caring. Therefore, there is no certainty as to whether memory will be allocated. Because of the GC (garbage collection mechanism), it is understood that the memory is reclaimed or a memory consumption token is reclaimed. If it is the latter, then the memory of the string is not timely recovery, and there is a large number of operations, which is likely to cause the program crashes, which is not safe, so the timely release of memory. It also shows that JNI has lost some of its security to Java, requiring programmers to think about it.
1.2 Arrays
Here the code is not affixed, the previous article has a section on the two-dimensional array of code.
An array is a collection of basic data types, called Findclass, to obtain a one-dimensional array of types. You can call Newobjectarray to assign an array of objects. It is also the stirng operation mode.
An array type is no longer passed as a basic data type, and it is roughly similar to the way that the class members and methods are accessed below. There's not much to say here.
2: Access to members and methods of the class
2.1 How members are accessed
There are two ways to access static members and instance members. In fact, the process is the same, the static member access is posted here, instance members as long as the implementation of the static removal of the method can be, in fact, this is the VS will automatically prompt you. Just feel free to use it boldly.
Accessing static members of a class jniexport void Jnicall Java_staticfield_accessfield (jnienv *env, Jobject obj) {jclass jcls;jint Num;jfieldID jfid;//Get jclassjcls = (*env)->getobjectclass (env, obj);
Like Getobjectclass and Findclass, they can get jclass. The former requires a reference to the JNI incoming, which requires the full class name if (NULL = = JCLs) {return;} Get Jfieldjfid = (*env)->getstaticfieldid (env, JCLS, "num", "I");//And the difference to get instance member ID is the addition of staticif (NULL = = Jfid) {return;} Get member Value num = (*env)->getstaticintfield (env, JCLS, Jfid);p rintf ("in c:\n");p rintf ("Staticfield.num =%d\n", num);// Build and modify values (*ENV)->setstaticintfield (env, JCLS, Jfid, 9999);}
How to access Class 2.2 methods
Jniexport void Jnicall Java_staticmethod_staticmethod (jnienv *env, Jobject obj) {jclass Jcls;jmethodid jmid;jcls = (*env) ->getobjectclass (env, obj); if (NULL = = JCLs) {return;} Jmid = (*env)->getstaticmethodid (Env,jcls, "Callback", "() V"); if (NULL = = Jmid) {return;} Improved method static Jmethodid jmid_s;if (NULL = = jmid_s) {jmid_s = (*env)->getstaticmethodid (env, JCLS, "callback", "() V"); if (NULL = = jmid_s) {return;}} Then change the bottom jmid to jmid_s so that it can be loaded once, knowing that the unload will no longer query the name and symbol table//You can cache the initialized field and method. This will update the value if it is loaded again. Improvement Two: Loading all the field and method information of a class into the hash table when it is first loaded. The next operation as long as the most of the table operation is OK. Use name and type to do key value printf ("In C call the Java instance method:\n-------------\ n");(*env)->callstaticvoidmethod (env, JCLS, JMID);}
2.3 How to access optimization
See comments in the change code. The same can be analogous to other ways of total
3: About global references and local references
JNI supports 3 kinds of references, global references, local references, weak global references.
Global references: Like all variables, the program must be actively created by the programmer by Newglobalref.
Local reference: Each creation of an instance returns a local reference to the instance, only valid in the native method in this thread. When native returns, it is automatically released.
The weak global reference attribute is the same as globalref, but a reference to that type is not guaranteed to be automatically recycled
"Explore Jni__2 Again"