最后一步我们需要做的是实现调用该本地方法的Java代码,如:
1 package mytest;
2 public class MyTest {
3 //这里调用loadLibrary方法用于加载该动态库到JVM中,以保证在使用时该方法已经被加载。
4 static {
5 System.loadLibrary("HelloNative");
6 }
7 public static void main(String[] args) throws Exception {
8 HelloNative.greeting();
9 }
10 }
11 /* 输出结果如下:
12 Hello, Native World!
13 */
2. 带有数值类型参数和返回值的本地方法:
先介绍一下Java中原始类型和C语言(JNI)中原始类型之间的对照关系,以及他们所占有的字节数量:
Java语言 C语言 字节数量
boolean jboolean 1
byte jbyte 1
char jchar 2
short jshort 2
int jint 4
long jlong 8
float jfloat 4
double jdouble 8
1) 编写带有native方法的Java代码:
1 package mytest;
2 public class Printf {
3 public static native int print(int width,int precision,double x);
4 static {
5 System.loadLibrary("Printf");
6 }
7 }
2) 编写与native方法对应的C语言代码:(记着先执行命令行命令javah mytest.Printf来生成mytest_Printf.h头文件)
1 #include "mytest_Printf.h"
2 #include
3 JNIEXPORT jint JNICALL Java_mytest_Printf_print(JNIEnv* env, jclass cl
4 ,jint width, jint precision, jdouble x)
5 {
6 char fmt[30];
7 jint ret;
8 sprintf(fmt,"%%%d.%df",width,precision);
9 ret = printf(fmt,x);
10 fflush(stdout);
11 return ret;
12 }
3) 编写调用native方法的Java测试代码:
1 package mytest;
2 public class MyTest {
3 public static void main(String[] args) throws Exception {
4 int count = Printf.print(8,4,3.14);
5 count += Printf.print(8,4,count);
6 System.out.println();
7 for (int i = 0; i < count; ++i) {
8 System.out.print("-");
9 }
10 System.out.println();
11 }
12 }
13 /* 输出结果如下:
14 3.1400 8.0000
15 ----------------
16 */
3. 带有字符串参数的本地方法:
JNI中提供了一组C语言的函数用于帮助在Java和C之间传递字符串数据,下面的代码会给出详细的注释说明。
1) 编写带有native方法的Java代码:
1 public class Printf {
2 public static native int print(String format,double x);
3 static {
4 System.loadLibrary("Printf");
5 }
6 }
2) 编写与native方法对应的C语言代码:
1 #include "Printf.h"
2 #include
3 #include
4 #include
5 JNIEXPORT jstring JNICALL Java_Printf_print
6 (JNIEnv* env, jclass cl, jstring format, jdouble x)
7 {
8 //1. 这里通过C语言调用JNI本地函数时,需要将参数env解引用之后在调用。
9 //env是指向所有JNI本地函数指针表的指针。
10 //2. 返回"改良UTF-8"编码的字符串的指针,或者当不能构建字符数组时返回NULL。
11 //直到RelaseStringUTFChars函数调用前,该指针一致有效。
12 //3. 由于Java针对字符串使用了对象池的技术,因此这里一定不能修改返回的const char*
13 const char* cformat = env->GetStringUTFChars(format,NULL);
14 //4. 获取参数中jstring的长度(GetStringUTFLength)
15 char* cret = (char*)calloc(env->GetStringUTFLength(format) + 20,1);
16 sprintf(cret,cformat,x);
17 //5. 根据"改良UTF-8"字节序列,返回一个新的Java对象,或者当字符串构造时,返回NULL。
18 jstr