注:开源力量Hadoop Development网络培训个人笔记,培训链接:http://new.osforce.cn/course/52
1. JNI基础概念
JNI是Java Native Interface的缩写,中文为Java本地调用。从Java 1.1开始,Java Native Interface(JNI)标准成为Java平台的一部分,它允许Java代码和其他语言写的代码进行交互。
JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。
JNI数据类型,除了void,其他都是在基本数据类型前加字母j
Reasonsfor using JNI
Problems with JNI
接下来的例程,视频讲解的有点问题,仿照链接做反而更容易弄懂含义:http://stuf.ro/calling-c-code-from-java-using-jni
全文拷贝如下:
In this tutorial we'll be creating a Java application calling code froma native library. We'll have a Java application called HelloWorld which willcall the function helloFromC
from a shared library named ctest
, using JavaNative Interface.
First off, we'll create a file named HelloWorld.java
to contain theHelloWorld
class.
/* HelloWorld.java */ public class HelloWorld { native void helloFromC(); /* (1) */ static { System.loadLibrary("ctest"); /* (2) */ } static public void main(String argv[]) { HelloWorld helloWorld = new HelloWorld(); helloWorld.helloFromC(); /* (3) */ } }
Even though we didn't write any library yet, we can still compile the Javaapplication, because this is a dependency that will be resolved at runtime. So,let's compile the application:
javac HelloWorld.java
This will generate a HelloWorld.class
file containing the application.Running the application will now result in an error, as we expect, because thelibrary is not created yet:
java HelloWorld
Exception in thread "main" java.lang.UnsatisfiedLinkError: no ctest in java.library.path at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1754) at java.lang.Runtime.loadLibrary0(Runtime.java:823) at java.lang.System.loadLibrary(System.java:1045) at HelloWorld.(HelloWorld.java:6)
Alright, let's now start writing the ctest
library in C. To do that, we mustfirst generate a header file from the .class
file we created earlier. Thisheader file will contain the definition of the function as it must be presentin the C file.
javah HelloWorld
This command will generate a HelloWorld.h file in the same directory,containing the following code:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include/* Header for class HelloWorld */ #ifndef _Included_HelloWorld #define _Included_HelloWorld #ifdef __cplusplus extern "C" { #endif /* * Class: HelloWorld * Method: helloFromC * Signature: ()V */ JNIEXPORT void JNICALL Java_HelloWorld_helloFromC (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
We'll leave this file exactly as is, as the comment suggests, but we need tocopy the function definition. Copy the definition and put it in a new file,named ctest.c
:
/* ctest.c */ JNIEXPORT void JNICALL Java_HelloWorld_helloFromC (JNIEnv * env, jobject jobj) { }
Note that we gave names to the parameters. Now let's implement the function.Aside from our own includes, we also need to include jni.h
for this to work.So, modify the ctest.c
file to contain something like:
/* ctest.c */ #include#include JNIEXPORT void JNICALL Java_HelloWorld_helloFromC (JNIEnv * env, jobject jobj) { printf("Hello from C!\n"); }
Now that we have the file, let's compile it and create a native library. Thispart is system dependent, but the only things that change really are theextension of the generated library file and the path to the jni.h
include.
gcc -o libctest.so -shared -I/path/to/jdk/headers ctest.c -lc
Replace .so
with .dylib
if you're on a Mac, or .dll
if you're on Windows(remove the lib
part from the file name as well if you're on Windows). Also,replace /path/to/jdk/headers
with the full path to the directory containingthe file jni.h
. If you don't know where that is, you can use the locatejni.h
command on UNIX-like systems.
Once you successfully run the above command, you will see a libctest.so
filein the current directory (or libctest.dylib
or libctest.dll
). If youremember from the Java code you wrote earlier, the virtual machine will expecta library named ctest
to reside in the current directory (point 2). By that,it means that a file with the name libctest.so
should be here, which you justcreated.
To see this in action, run the application:
java HelloWorld
If everything works correctly, you should see:
Hello from C!