From C + + to Java, and then back to C + + from Java, today finally have the opportunity to understand the connection between Java, C + + bridge--jni. Ha ha! Share it!
First, Introduction
JNI is a shorthand for Java Native Interface, which can be translated into Java native interfaces. Java can invoke C + + libraries through JNI, which is a good way for those Java programs that have higher performance requirements or for tasks that Java cannot handle.
Second, the purpose: Java code in the call to C + + code
Iii. implementation: Suppose our Java program is J2c.java, c program is J2C.C, the communication function between Java and C is named Write2proc;
Then Write2proc's statement is located in J2c.java, where J2C.C is implemented;
Four, operation
1. Write and compile Java programs
Javac J2c.java => J2c.class
2. To generate C + + header files
Javah j2c => J2C.h (after installing JDK, $JAVA _home should have joined $path, otherwise absolute path, such as/usr/bin/javah)
3. Write the corresponding C + + program: J2C.C
4. Generate the C + + target file
Gcc-i/usr/lib/jvm/java-6-openjdk-amd64/include-i/usr/lib/jvm/java-6-openjdk-amd64/include/linux-fpic-c J2C.c = > J2C.O
5. Generate A/C + + shared library
Gcc-shared-wl,-soname,libj2c.so.1-o libj2c.so.1.0 J2C.O => libj2c.so.1.0
6. Rename cp libj2c.so.1.0 libj2c.so => libj2c.so
7. Add a shared library to the path of the dynamic link library (This example is the current directory)
Export ld_library_path= $LD _library_path:.
8. Execute Java programs to enable cross-language communication
Java j2c
V. Specific processes
1. Write and compile J2c.java
Copy Code code as follows:
Import Java.lang.management.ManagementFactory;
Import Java.lang.management.RuntimeMXBean;
public class J2C
{
Static
{
try{
Here is the name of the link library where the local method is located
System.loadlibrary ("j2c");
catch (Unsatisfiedlinkerror e)
{
SYSTEM.ERR.PRINTLN ("Cannot load j2c library:\n" +
E.tostring ());
}
}
Declared local method
public static native int write2proc (int pid);
public static void Main (string[] args) {
Gets the PID of this process (that is, the main thread)
Final Runtimemxbean runtime = Managementfactory.getruntimemxbean ();
Final String info = runtime.getname ();
Final int index = Info.indexof ("@");
if (index!=-1) {
final int pid = integer.parseint (info.substring (0, index));
SYSTEM.OUT.PRINTLN (info);
SYSTEM.OUT.PRINTLN (PID);
Write2proc (PID);
}
try{
Thread.Sleep (8000);
catch (Interruptedexception e) {
E.printstacktrace ();
}
}
}
The system.loadlibrary parameter name in the Note:java program represents the C + + shared library to load, and the shared library name that is generated in step 6th must be consistent with this parameter, that is, system.loadlibrary (name) corresponds to the shared library name Libname.so ( Shared library name must begin with Lib)
2. Generate C header file J2c.h:javah j2c
Copy Code code as follows:
/* Do isn't EDIT this file-it is machine generated * *
#include <jni.h>
/* Header for class J2C * *
#ifndef _INCLUDED_J2C
#define _INCLUDED_J2C
#ifdef __cplusplus
extern "C" {
#endif
/*
* CLASS:J2C
* Method:write2proc
* Signature: (i) I
*/
Jniexport Jint Jnicall Java_j2c_write2proc
(JNIEnv *, Jclass, jint);
#ifdef __cplusplus
}
#endif
#endif
Note:1. Header file automatically generated, do not modify it;
2. Function Jniexport jint jnicall java_j2c_write2proc (jnienv *, Jclass, jint);
According to the annotation is defined in the J2c.java file class j2c method Write2proc, so the C program implementation function must be consistent with the signature of the place;
3. Writing C program J2C.C
Copy Code code as follows:
#include <stdio.h>
#include "J2C.h"
Jniexport int Jnicall Java_j2c_write2proc (jnienv * env, jobject ARG, jint pid)
{
printf ("Current PID is%d\n", PID);
return 0;
}
4. Compile C program
Because the C program #include "J2C.h" and J2C.h and #include <jni.h>, and GCC inside the default environment does not know what jni.h is, so compile-time need to tell the compiler jni.h location (jni.h in the JDK $java _home/include below), so that only the above compilation parameters;
Because using GCC to compile a dynamic library, some situations may be abnormal when JNI calls, and you can try to use g++ instead.
Summarize
1. The prototype declaration of a method in Java must be consistent with the corresponding implementation file definition of C/n + + (which can be compared by an automatically generated C + + header file), especially the class name and method name;
2. The shared library name that System.loadlibrary () is loaded in Java must be the same as the shared library name that is generated later in C + + +.