Java programming-everything you should know about JNI, Java programming-JNI

Source: Internet
Author: User

Java programming-everything you should know about JNI, Java programming-JNI

Due to efficiency issues, in many cases, we need to call the underlying C or C ++ implementation in the upper-layer Java code, so that jni can be used. Jni (Java Native Interface) allows Java code to interact with code written in other languages. Using java to interact with locally compiled code usually results in loss of platform portability. However, in some cases, this is acceptable or even necessary. For example, you can use some old libraries to interact with hardware and operating systems, or to improve program performance.

Steps for JNI Programming

About javah: run the javah-h command in the Command window. We can see all the options of javah. Here is a brief introduction:

  • -Classpath: used to load the class path
  • -D: output directory
  • -O, output file,-d, and-o can only use one of them
  • -Jni: generate the header file of the jni style (default)
Write the first JNI Program

As you can see the above steps, we will try to use jni to write a simple hello world Program.
1. First, we use Java code to write a local method hello:

package com.example.jnitest;public class JniTest {    public static native void hello();}

2. Next we will use javah to generate the header file. Note that we should first compile the project to obtain the. class file. Then run the command line to go to the project directory/bin directory and enter the command javah-classpath. com. example. jnitest. JniTest to get the header file,

The code for getting the header file is as follows:

/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_example_jnitest_JniTest */#ifndef _Included_com_example_jnitest_JniTest#define _Included_com_example_jnitest_JniTest#ifdef __cplusplusextern "C" {#endif/* * Class:     com_example_jnitest_JniTest * Method:    hello * Signature: ()V */JNIEXPORT void JNICALL Java_com_example_jnitest_JniTest_hello  (JNIEnv *, jclass);#ifdef __cplusplus}#endif#endif

3. next, we will use the C language to implement our program. To facilitate the creation of shared library files, here I create a console project in VS2012 and select dll and empty projects in application settings.

Add the obtained header file and create a cpp file to implement our program.

#include"jni_hello.h"JNIEXPORT void JNICALL Java_com_example_jnitest_JniTest_hello    (JNIEnv *, jclass){        printf("Hello Jni!\n");}

NOTE: If we add the header file directly, the header file jni may not be found. h. In this case, we need to configure our project, right-click the project-> properties-> VC ++ directory, select include directory-> edit, and add the directory of the jni header file, the include folder and include/win32 folder under the jdk directory are the directories to be added,

4. generate the shared library file. Next, run the project and find it in the Debug folder. dll file. Note that vs directly generates a 32-bit dll file. If your machine is 64-bit, the error "Can't load IA 32-bit" will be reported. dll on a AMD 64-bit platform, then we will configure our VS project: generate-> Configure the manager's active solution platform, activity solution platform-> New-> select x64

Next we need to add our shared library:

  • First, call System. out. println (System. getProperty ("java. library. path") to obtain the path of the shared library.
  • Next we will copy the dll file to one of the paths

5. Load the shared library and call the native method:

Package com. example. jnitest; public class Main {static {System. loadLibrary ("JniApplication"); // static initialization block loading library} public static void main (String [] args) {JniTest. hello ();}}

Output results in the console:

Data Type ing in Jni

After learning about the simple usage of jni, let's take a further look: First, let's make the correspondence between the basic Java types and C Types in jni

In addition to the basic data types, common data types are strings. in Java, the String corresponds to jstring in C. We can convert the jstring type and char * using the following method:

Char * ff = "Hello Jni! "; // Create a jstring j_string = env-> NewStringUTF (ff ); // convert the jstring type to char * const char * c_string = env-> GetStringUTFChars (j_string, 0); printf (c_string); // when the string is no longer used, to release env-> ReleaseStringUTFChars (j_string, c_string );
Access the domain in Java

To access the fields and methods in Java by using C language, you must know the Id. It is relatively complicated to use. Here is a simple example, assume that our class People has an int type field age, that is:

package com.example.jnitest;public class People {    private int age;    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }}

Modify the method in JniTest. This time, we call the native method to change the age field to twice the original one:

package com.example.jnitest;public class JniTest {    public static native People changeAge(People people);}

After the header file is regenerated, compile our method in the cpp file. To access the Java domain, we need to obtain FieldId. The procedure is as follows:
1. Class for obtaining implicit Parameters
2. Obtain the domain Id
3. Access Domain value

# Include "jni_hello.h" JNIEXPORT jobject JNICALL evaluate (JNIEnv * env, jclass cl, jobject ob) {jclass cl_people = env-> GetObjectClass (ob ); jfieldID c_ageId = env-> GetFieldID (cl_people, "age", "I"); jint c_age = env-> GetIntField (ob, c_ageId ); // print the modified statement printf ("% d", c_age); // modify the age field env-> SetIntField (ob, c_ageId, 2 * c_age); return ob ;}

The second parameter in the env-> GetFieldID method indicates the name of the field, and the third parameter indicates that the type of the age field is int. The jni encoding signature is related and will be mentioned later. Next, call the main method:

package com.example.jnitest;public class Main {    static{        System.loadLibrary("JniApplication");    }    public static void main(String[] args) {        People people = new People();        people.setAge(5);        people = JniTest.changeAge(people);        System.out.println("changed::"+people.getAge());    }}

Output result:

As you can see, the result is 2 times the original one. When accessing a static domain, you only need to change env-> GetIntField to env-> GetStaticIntField.

Access methods in Java

We just used the method to access the domain to modify the value of the domain. Next we will call the setAge method in the People class in the cpp file to modify the value of the age; to call a Java method, follow these steps:

# Include "jni_hello.h" JNIEXPORT jobject JNICALL evaluate (JNIEnv * env, jclass cl, jobject ob) {jclass cl_people = env-> GetObjectClass (ob ); jfieldID c_ageId = env-> GetFieldID (cl_people, "age", "I"); jint c_age = env-> GetIntField (ob, c_ageId ); // The third parameter is also related to the encoding signature. jmethodID c_setAgeId = env-> GetMethodID (cl_people, "setAge", "(I) V"); // void indicates the return type, if the return value is int, call CallIntMethod env-> CallVoidMethod (ob, c_setAgeId, 2 * c_age); return ob ;}

In the main function, the Code is the same as above. The result is as follows:

For static method calls, we only need to replace the method used during the call. For example, if the setAge method is static, we only need to change env-> CallVoidMethod (ob, c_setAgeId, 2 * c_age ); change to env-> CallStaticVoidMethod (ob, c_setAgeId, 2 * c_age.

Jni-encoded Signature

As mentioned above, the third parameter in the env-> GetFieldID method uses an encoded signature to represent the Data Type of the domain. Now we will introduce the correspondence between data classes in jni.

  • Basic Data Type:
    B -- byte, C -- char, D -- double, F -- float,
    I --- int, J -- long, S -- short, V --- void, Z -- boolean
  • Array type. "[" is added at the beginning. For example, if the int [] array is "[I", the two-dimensional array int [] [] is "[I"
  • Class type, with "L + complete package name + class name +;" indicating all ". "to"/", such as com. example. jnitest. the People class is Lcom/example/jnitest/People;

The encoding signature rules for methods are as follows: "(encoding signature of input parameter type) + Response Parameter type encoding signature". Multiple Input parameters can be directly connected; for example, if the input parameter in our setAge method is int and the return value is void, it is expressed as "(I) V ".

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.