对于别人写的linux下的jni写的真的不清晰、明了,甚至会出现错误;对于代码重点的就是不会的人用你的代码就可以执行就ok了!!好了,废话不说了,来开始咱们的jni了;
首先咱们得理解一下jni的概念吧: jni(java
native
interface)java原生接口;对于学习过java的我们并不陌生接口的概念吧,接口就是定义一系列的方法,让其实现类来实现;好了,咱们直接上代码,用代码来解决一切;
第一个程序:对于java类的属性赋值:
首先看看完成后的文件:
首先新建TestInt.java :
public class TestInt{public native void setInt(int a);
public native int getInt();
static{
System.loadLibrary("TestInt");
}
public static void main(String args[]){TestInt testInt = new TestInt();
testInt.setInt(5);
System.out.println("你要输出的值为:"+testInt.getInt());
}
}
然后进行编译:javac TestInt.java
生成TestInt.class计算机可以读取的二进制文件,依靠此二进制文件生成头文件 TestInt.h
指令为:javah -jni TestInt
生成了TestInt.h文件:其代码如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class TestInt */#ifndef _Included_TestInt
#define _Included_TestInt
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: TestInt
* Method: setInt
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_TestInt_setInt
(JNIEnv *, jobject, jint);/*
* Class: TestInt
* Method: getInt
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_TestInt_getInt
(JNIEnv *, jobject);#ifdef __cplusplus
}
#endif
#endif
咱们可以看到这里有两个方法分别如上图代码所示:
咱们要在写一个c语言代码,来实现对于其方法的实现:说白了,其方法就是接口中要实现的方法:新建一个TestInt.cpp
#include<jni.h>
#include"TestInt.h"int b;
JNIEXPORT void JNICALL Java_TestInt_setInt
(JNIEnv *env, jobject obj, jint a){
b=3+a;
}JNIEXPORT jint JNICALL Java_TestInt_getInt
(JNIEnv * env, jobject obj){
return b;
}
ok!以上代码已经完成,接下来就是要生成动态库了:
g++ -I/usr/java/jdk1.6.0_43/include/linux
-I/usr/java/jdk1.6.0_43/include -fpic -shared -o libTestInt.so TestInt.cpp
如果你要是这样写: g++
-fpic -shared -o libTestInt.so TestInt.cpp会抛出如下异常:
TestInt.cpp:1:16: 错误:jni.h:没有那个文件或目录
TestInt.h:15: 错误:expected constructor, destructor, or type conversion before ‘void’
TestInt.h:23: 错误:‘JNIEXPORT’ 没有命名一个类型
TestInt.cpp:5: 错误:expected constructor, destructor, or type conversion before ‘void’
TestInt.cpp:10: 错误:‘JNIEXPORT’ 没有命名一个类型
所以必须要指明jdk的头文件的路径,以及include目录下其他资源文件的路径;
最后一条指令:java Djava.dictionary.path=.
TestInt
输出结果:你要输出的值为:8
另外一个程序:关于无返回值字符串的输出程序:
首先也一样将结果目录图片显示出来:
我也不那么多废话了:直接将各个文件的代码复制到页面:
public class TestJni{public native void print(String context);
static{
System.loadLibrary("TestJni");
}
}
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class TestJni */#ifndef _Included_TestJni
#define _Included_TestJni
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: TestJni
* Method: print
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_TestJni_print
(JNIEnv *, jobject, jstring);#ifdef __cplusplus
}
#endif
#endif
#include <jni.h>
#include "TestJni.h"
JNIEXPORT void JNICALL Java_TestJni_print
(JNIEnv *env, jobject obj, jstring content){const jbyte *str=( const jbyte *)(*env)->GetStringUTFChars(env,content,JNI_FALSE);
printf("Hello,%s\n",str);
(*env)->ReleaseStringUTFChars(env, content, (const char *)str );
}
public class HelloWorld{public static void main(String args[]){
new HelloWorld();
}
public HelloWorld(){
new TestJni().print("yuchao");
}
}
各个操作过程第一个程序写的很清楚了,所以这里我就不写了;