Java JNI 编程进阶
- 1. java JNI 编程进阶
JNI 一直以来都很少去关注,但却是我心中的一个结,最近这几天刚好手头有点时间,因此抽
空看了一下这方面的东西,整理了一份文档,JNI 技术的出现主要是基于三个方面的应用需
求:
1. 解决性能问题
Java 具有平台无关性,这使人们在开发公司级应用的时候总是把它作为主要候选方案之一,但
是性能方面的因素又大大削弱 了它的竞争力。为此,提高 Java 的性能就显得十分重要。Sun
公司及 Java 的支持者们为提高 Java 的运行速度已经做出了许多努力,其中大多数集中在 程
序设计的方法和模式选择方面。由于算法和设计模式的优化是通用的,对 Java 有效的优化算
法和设计模式,对其他编译语言也基本同样适用,因此不能从根本 上改变 Java 程序与编译型
语言在执行效率方面的差异。由此,于是人们开始引入 JIT(Just In Time,及时编译)的概
念。它的基本原理是:首先通过 Java 编译器把 Java 源代码编译成平台无关的二进制字节码。
然后在 Java 程序真正执行之前, 系统通过 JIT 编译器把 Java 的字节码编译为本地化机器码。
最后,系统执行本地化机器码,节省了对字节码进行解释的时间。这样做的优点是大大提高了
Java 程序的性能,缩短了加载程序的时间;同时,由于编译的结果并不在程序运行间保存,因
此也节约了存储空间。缺点是由于 JIT 编译器对所有的代码都想 优化,因此同样也占用了很多
时间。
动态优化技术是提高 Java 性能的另一个尝试。该技术试图通过把 Java 源程序直接编译成机器
码,以充分利用 Java 动态编译和静态编译技术来提高 Java 的性能。该方法把输入的 Java 源
码或字节码转换为经过高度优化的可执行代码和动态库 (Windows 中的. dll 文件或 Unix 中
的. so 文件)。该技术能大大提高程序的性能,但却破坏了 Java 的可移植性。
JNI(Java Native Interface, Java 本地化方法)技术由此闪亮登场。因为采用 JNI 技术只是针
对一些严重影响 Java 性能的代码段,该部分可能只占源程序的极少部分,所以几乎可以不 考
虑该部分代码在主流平台之间移植的工作量。同时,也不必过分担心类型匹配问题,我们完全
可以控制代码不出现这种错误。此外,也不必担心安全控制问题,因 为 Java 安全模型已扩展
为允许非系统类加载和调用本地方法。根据 Java 规范,从 JDK 1. 2 开始,FindClass 将设法
找到与当前的本地方法关联的类加载器。如果平台相关代码属于一个系统类,则无需涉及任何
类加载器; 否则,将调用适当的类加载器来加载和链接已命名的类。换句话说,如果在 Java 程
序中直接调用 C/C++语言产生的机器码,该部分代码的安全性就由 Java 虚拟机控制。
2. 解决本机平台接口调用问题
JAVA 以其跨平台的特性深受人们喜爱,而又正由于它的跨平台的目的,使得它和本地机器的
各种内部联系变得 很少,约束了它的功能。解决 JAVA 对本地操作的一种方法就是
JNI。JAVA 通过 JNI 调用本地方法,而本地方法是以库文件的形式存放的(在 WINDOWS 平
台上是 DLL 文件形式,在 UNIX 机器上是 SO 文件形式)。通过调用本地的库文件的内部方
法,使 JAVA 可以实现和本地机器的紧密联系, 调用系统级的各接口方法。
- 2. 3. 嵌入式开发应用
“一次编程,到处使用”的 Java 软件概念原本就是针对网上嵌入式小设备提出的,几经周折,
目前 SUN 公司已推出了 J2ME(Java 2 P1atform Micro Edition)针对信息家电的 Java 版
本,其技术日趋成熟,开始投入使用。SUN 公司 Java 虚拟机(JVM)技术的有序开放,使得
Java 软件真正 实现跨平台运行,即 Java 应用小程序能够在带有 JVM 的任何硬软件系统上执
行。加上 Java 语言本身所具有的安全性、可靠性和可移植性等特点,对实现瘦 身上网的信息
家电等网络设备十分有利,同时对嵌入式设备特别是上网设备软件编程技术产生了很大的影
响。也正是由于 JNI 解决了本机平台接口调用问题,于是 JNI 在嵌入式开发领域也是如火如
荼。
不失直观性,我们首先写一个 JNI 小例子:
Java 代码
1. public class HelloJni {
2. public native void displayHelloJni();
3.
4. static {
5. System.loadLibrary("helloJni");
6. }
7.
8. public static void main(String[] args) {
9. //System.out.println(System.getProperty("java.library.path"));
10. new HelloJni().displayHelloJni();
11. }
12.} public class HelloJni {
13. public native void displayHelloJni();
14.
15. static {
16. System.loadLibrary("helloJni");
17. }
18.
19. public static void main(String[] args) {
20. //System.out.println(System.getProperty("java.library.p
ath"));
21. new HelloJni().displayHelloJni();
22. }
23.}
- 3. 在 class 文件生成的相应目录执行命令如下:
----------------------------------------------------
E:projectsjnitargetclasses>javah HelloJni
----------------------------------------------------
得到 C++文件 HelloJni.h
Cpp 代码
1. /* DO NOT EDIT THIS FILE - it is machine generated */
2. #include <jni.h>
3. /* Header for class HelloJni */
4.
5. #ifndef _Included_HelloJni
6. #define _Included_HelloJni
7. #ifdef __cplusplus
8. extern "C" {
9. #endif
10./*
11. * Class: HelloJni
12. * Method: displayHelloJni
13. * Signature: ()V
14. */
15.JNIEXPORT void JNICALL Java_HelloJni_displayHelloJni
16. (JNIEnv *, jobject);
17.
18.#ifdef __cplusplus
19.}
20.#endif
21.#endif /* DO NOT EDIT THIS FILE - it is machine generated */
22.#include <jni.h>
23./* Header for class HelloJni */
24.
25.#ifndef _Included_HelloJni
26.#define _Included_HelloJni
27.#ifdef __cplusplus
28.extern "C" {
29.#endif
30./*
31. * Class: HelloJni
32. * Method: displayHelloJni
33. * Signature: ()V
34. */
35.JNIEXPORT void JNICALL Java_HelloJni_displayHelloJni
36. (JNIEnv *, jobject);
- 4. 37.
38.#ifdef __cplusplus
39.}
40.#endif
41.#endif
JNI 函数名称分为三部分:首先是 Java 关键字,供 Java 虚拟机识别;然后是调用者类名称
(全限定的类名,其中用下划线代替名称分隔符);最后是对应的方法名称,各段名称之间用下
划线分割。
JNI 函数的参数也由三部分组成:首先是 JNIEnv *,是一个指向 JNI 运行环境的指针;第二个
参数随本地方法是静态还是非静态而有所不同一一非静态本地方法的第二个参数是对对象的引
用,而静态本地方法的 第二个参数是对其 Java 类的引用;其余的参数对应通常 Java 方法的
参数,参数类型需要根据一定规则进行映射。
编写 C++文件 HelloJni.h 的实现类,我是比较常用 VC6.0 来生成 dll 文件(helloJni.dll)的
Cpp 代码
1. #include <jni.h>
2. #include "HelloJni.h"
3. #include <stdio.h>
4.
5. JNIEXPORT void JNICALL
6. Java_HelloJni_displayHelloJni(JNIEnv *env, jobject obj)
7. {
8. printf("Hello Dynamic Link Library has been calling!n");
9. printf("Java_HelloJni_displayHelloJni method has been executed!n");
10. return;
11.} #include <jni.h>
12.#include "HelloJni.h"
13.#include <stdio.h>
14.
15.JNIEXPORT void JNICALL
16.Java_HelloJni_displayHelloJni(JNIEnv *env, jobject obj)
17.{
18. printf("Hello Dynamic Link Library has been calling!n");
19. printf("Java_HelloJni_displayHelloJni method has been
executed!n");
20. return;
- 5. 21.}
其实此时,我们的工程目前还暂时不能生成我们想要的 helloJni.dll 文件,问题就出在
了“#include <jni.h>”。由于 VC6.0 里没有我们需要的“jni.h”文件,因此就需要手动加入到
VC6.0 的环境中去。在 JAVA_HOME 路 径下我们可以找到 include 文件夹,其中就可以找到
我们需要的“jni.h”文件。为了避免以后麻烦起见,将所有的 C++文件全部拿出来,放在
“%CPP_HOME%VC98Include”路径下。然后将工程进行打包就可以得到我们需要
的“helloJni.dll”文件了。
将 helloJni.dll 文件放置于工程 classes 目录,执行命令如下:
-----------------------------------------------
E:projectsjnitargetclasses>java HelloJni
-----------------------------------------------
运行结果如下:
-----------------------------------------------------------------
Hello Dynamic Link Library has been calling!
Java_HelloJni_displayHelloJni method has been executed!
-----------------------------------------------------------------
但是要想在 eclipse 中运行 helloJni.dll 文件,就需要将文件拷贝到工程的根目录,或者将其放
在诸如 C:WINDOWS system32;C:WINDOWS;等目录下。因为,eclipse 在运行
helloJni.dll 文件时首先会去在当前根目录找,如果找不到则 在 path 上去找,因此你还可以为
了方便管理生成的 dll 文件,将所有工程中的 dll 文件都放到一个特定的目录,然后将该目录加
入到你的本地 path 环境 变量中去,这样每次只需要将生成的 dll 文件放入 path 目录下就可以
访问了。注,如果需要加环境变量最好在加好以后重新启动一下 eclipse,确保 eclipse 能够
加载到最新的 path 环境。
接下来,对小例子进行重构:
1. 新增一个基础类
Java 代码
1. package org.danlley.jni.test;
2.
3. public class BaseClass {
4.
5. public BaseClass(String arg) {
- 6. 6. loadLibrary(arg);
7. }
8.
9. private static void loadLibrary(String arg) {
10. System.loadLibrary(arg);
11. }
12.} package org.danlley.jni.test;
13.
14.public class BaseClass {
15.
16. public BaseClass(String arg) {
17. loadLibrary(arg);
18. }
19.
20. private static void loadLibrary(String arg) {
21. System.loadLibrary(arg);
22. }
23.}
2. 定义新类继承基础类
Java 代码
1. package org.danlley.jni.test;
2.
3. public class HelloJniTest extends BaseClass {
4. public HelloJniTest(String arg){
5. super(arg);
6. }
7. public native void displayHelloJni();
8. } package org.danlley.jni.test;
9.
10.public class HelloJniTest extends BaseClass {
11. public HelloJniTest(String arg){
12. super(arg);
13. }
14. public native void displayHelloJni();
15.}
3. 编写调用类
Java 代码
- 7. 1. package org.danlley.jni.test;
2.
3. public class RunMain {
4. public static void main(String[] args) {
5. new HelloJniTest("helloJniTest").displayHelloJni();
6. }
7. } package org.danlley.jni.test;
8.
9. public class RunMain {
10. public static void main(String[] args) {
11. new HelloJniTest("helloJniTest").displayHelloJni();
12. }
13.}
此次,将 dll 文件定义为:helloJniTest.dll。
执行结果:
------------------------------------------------------------------------------------
Java_org_danlley_jni_test_HelloJniTest_displayHelloJni has been called!
------------------------------------------------------------------------------------
例子相当简单,没有传入参数,也没有返回值,那么是不是可以让本地方法返回一些参数,同
时又可以传入数据进行处理,并把处理结果返回给方法的调用者呢,先拿基本类型开刀。接下
来对 HelloJniTest 继续进行改造:新增两个本地方法,如下:
Java 代码
1. package org.danlley.jni.test;
2.
3. public class HelloJniTest extends BaseClass {
4. public HelloJniTest(String arg){
5. super(arg);
6. }
7. public native void displayHelloJni();
8.
9. public native int getDynamicIntDataNoParam();
10.
11. public native int getDynamicIntData(int i);
12.} package org.danlley.jni.test;
13.
14.public class HelloJniTest extends BaseClass {
15. public HelloJniTest(String arg){
16. super(arg);
- 8. 17. }
18. public native void displayHelloJni();
19.
20. public native int getDynamicIntDataNoParam();
21.
22. public native int getDynamicIntData(int i);
23.}
重新生成 org_danlley_jni_test_HelloJniTest.h 文件,并改写其实现类
org_danlley_jni_test_HelloJniTest.cpp 如下:
Cpp 代码
1. // org_danlley_jni_test_HelloJniTest.cpp: implementation of the
org_danlley_jni_test_HelloJniTest class.
2. //
3. //////////////////////////////////////////////////////////////////////
4.
5. #include "org_danlley_jni_test_HelloJniTest.h"
6. #include <jni.h>
7. #include <stdio.h>
8.
9. JNIEXPORT void JNICALL
10.Java_org_danlley_jni_test_HelloJniTest_displayHelloJni(JNIEnv *env,
jobject obj)
11.{
12. printf("Java_org_danlley_jni_test_HelloJniTest_displayHelloJni has been
called!n");
13. return;
14.}
15.
16.JNIEXPORT jint JNICALL
17.Java_org_danlley_jni_test_HelloJniTest_getDynamicIntDataNoParam(JNIEn
v *env, jobject obj)
18.{
19. return 65535;
20.}
21.
22.JNIEXPORT jint JNICALL
23.Java_org_danlley_jni_test_HelloJniTest_getDynamicIntData(JNIEnv *env,
jobject obj, jint i)
24.{
25. i*=i;
26. return i;
- 9. 27.} // org_danlley_jni_test_HelloJniTest.cpp: implementation of
the org_danlley_jni_test_HelloJniTest class.
28.//
29.///////////////////////////////////////////////////////////////
///////
30.
31.#include "org_danlley_jni_test_HelloJniTest.h"
32.#include <jni.h>
33.#include <stdio.h>
34.
35.JNIEXPORT void JNICALL
36.Java_org_danlley_jni_test_HelloJniTest_displayHelloJni(JNIEnv
*env, jobject obj)
37.{
38. printf("Java_org_danlley_jni_test_HelloJniTest_displayHello
Jni has been called!n");
39. return;
40.}
41.
42.JNIEXPORT jint JNICALL
43.Java_org_danlley_jni_test_HelloJniTest_getDynamicIntDataNoParam
(JNIEnv *env, jobject obj)
44.{
45. return 65535;
46.}
47.
48.JNIEXPORT jint JNICALL
49.Java_org_danlley_jni_test_HelloJniTest_getDynamicIntData(JNIEnv
*env, jobject obj, jint i)
50.{
51. i*=i;
52. return i;
53.}
修改 RunMain 类:
Java 代码
1. package org.danlley.jni.test;
2.
3. public class RunMain {
4. public static void main(String[] args) {
5. HelloJniTest tester=new HelloJniTest("helloJniTest");
6. tester.displayHelloJni();
7. int i=tester.getDynamicIntDataNoParam();
8. System.out.println("tester.getDynamicIntDataNoParam()="+i);
- 10. 9. int j=tester.getDynamicIntData(100);
10. System.out.println("tester.getDynamicIntData(100)="+j);
11. }
12.} package org.danlley.jni.test;
13.
14.public class RunMain {
15. public static void main(String[] args) {
16. HelloJniTest tester=new HelloJniTest("helloJniTest");
17. tester.displayHelloJni();
18. int i=tester.getDynamicIntDataNoParam();
19. System.out.println("tester.getDynamicIntDataNoParam()="
+i);
20. int j=tester.getDynamicIntData(100);
21. System.out.println("tester.getDynamicIntData(100)="+j);
22. }
23.}
运行 RunMain:
-----------------------------------------------------------------------
tester.getDynamicIntDataNoParam()=65535
tester.getDynamicIntData(100)=10000
Java_org_danlley_jni_test_HelloJniTest_displayHelloJni has been called!
-----------------------------------------------------------------------
OK,一切正常。
还是不过瘾,简单对象可以处理了,如果是一个 java 对象,还可以处理吗,答案是当然可以,
接下来我们来继续对 helloJniTest 类进行改造。新增一个方法如下:
Java 代码
1. package org.danlley.jni.test;
2.
3. public class HelloJniTest extends BaseClass {
4. public HelloJniTest(String arg){
5. super(arg);
6. }
7. public native void displayHelloJni();
8.
9. public native int getDynamicIntDataNoParam();
10.
11. public native int getDynamicIntData(int i);
- 11. 12.
13. public native String getDynamicStringData(String arg);
14.} package org.danlley.jni.test;
15.
16.public class HelloJniTest extends BaseClass {
17. public HelloJniTest(String arg){
18. super(arg);
19. }
20. public native void displayHelloJni();
21.
22. public native int getDynamicIntDataNoParam();
23.
24. public native int getDynamicIntData(int i);
25.
26. public native String getDynamicStringData(String arg);
27.}
重新生成 org_danlley_jni_test_HelloJniTest.h 文件:
Cpp 代码
1. /* DO NOT EDIT THIS FILE - it is machine generated */
2. #include <jni.h>
3. /* Header for class org_danlley_jni_test_HelloJniTest */
4.
5. #ifndef _Included_org_danlley_jni_test_HelloJniTest
6. #define _Included_org_danlley_jni_test_HelloJniTest
7. #ifdef __cplusplus
8. extern "C" {
9. #endif
10./*
11. * Class: org_danlley_jni_test_HelloJniTest
12. * Method: displayHelloJni
13. * Signature: ()V
14. */
15.JNIEXPORT void JNICALL
Java_org_danlley_jni_test_HelloJniTest_displayHelloJni
16. (JNIEnv *, jobject);
17.
18./*
19. * Class: org_danlley_jni_test_HelloJniTest
20. * Method: getDynamicIntDataNoParam
21. * Signature: ()I
22. */
- 12. 23.JNIEXPORT jint JNICALL
Java_org_danlley_jni_test_HelloJniTest_getDynamicIntDataNoParam
24. (JNIEnv *, jobject);
25.
26./*
27. * Class: org_danlley_jni_test_HelloJniTest
28. * Method: getDynamicIntData
29. * Signature: (I)I
30. */
31.JNIEXPORT jint JNICALL
Java_org_danlley_jni_test_HelloJniTest_getDynamicIntData
32. (JNIEnv *, jobject, jint);
33.
34./*
35. * Class: org_danlley_jni_test_HelloJniTest
36. * Method: getDynamicStringData
37. * Signature: (Ljava/lang/String;)Ljava/lang/String;
38. */
39.JNIEXPORT jstring JNICALL
Java_org_danlley_jni_test_HelloJniTest_getDynamicStringData
40. (JNIEnv *, jobject, jstring);
41.
42.#ifdef __cplusplus
43.}
44.#endif
45.#endif /* DO NOT EDIT THIS FILE - it is machine generated */
46.#include <jni.h>
47./* Header for class org_danlley_jni_test_HelloJniTest */
48.
49.#ifndef _Included_org_danlley_jni_test_HelloJniTest
50.#define _Included_org_danlley_jni_test_HelloJniTest
51.#ifdef __cplusplus
52.extern "C" {
53.#endif
54./*
55. * Class: org_danlley_jni_test_HelloJniTest
56. * Method: displayHelloJni
57. * Signature: ()V
58. */
59.JNIEXPORT void JNICALL
Java_org_danlley_jni_test_HelloJniTest_displayHelloJni
60. (JNIEnv *, jobject);
61.
62./*
63. * Class: org_danlley_jni_test_HelloJniTest
64. * Method: getDynamicIntDataNoParam
65. * Signature: ()I
66. */
- 13. 67.JNIEXPORT jint JNICALL
Java_org_danlley_jni_test_HelloJniTest_getDynamicIntDataNoParam
68. (JNIEnv *, jobject);
69.
70./*
71. * Class: org_danlley_jni_test_HelloJniTest
72. * Method: getDynamicIntData
73. * Signature: (I)I
74. */
75.JNIEXPORT jint JNICALL
Java_org_danlley_jni_test_HelloJniTest_getDynamicIntData
76. (JNIEnv *, jobject, jint);
77.
78./*
79. * Class: org_danlley_jni_test_HelloJniTest
80. * Method: getDynamicStringData
81. * Signature: (Ljava/lang/String;)Ljava/lang/String;
82. */
83.JNIEXPORT jstring JNICALL
Java_org_danlley_jni_test_HelloJniTest_getDynamicStringData
84. (JNIEnv *, jobject, jstring);
85.
86.#ifdef __cplusplus
87.}
88.#endif
89.#endif
改写 org_danlley_jni_test_HelloJniTest.cpp 文件:
Cpp 代码
1. // org_danlley_jni_test_HelloJniTest.cpp: implementation of the
org_danlley_jni_test_HelloJniTest class.
2. //
3. //////////////////////////////////////////////////////////////////////
4.
5. #include "org_danlley_jni_test_HelloJniTest.h"
6. #include <jni.h>
7. #include <stdio.h>
8.
9. JNIEXPORT void JNICALL
10.Java_org_danlley_jni_test_HelloJniTest_displayHelloJni(JNIEnv *env,
jobject obj)
11.{
12. printf("Java_org_danlley_jni_test_HelloJniTest_displayHelloJni has been
called!n");
- 14. 13. return;
14.}
15.
16.JNIEXPORT jint JNICALL
17.Java_org_danlley_jni_test_HelloJniTest_getDynamicIntDataNoParam(JNIEn
v *env, jobject obj)
18.{
19. return 65535;
20.}
21.
22.JNIEXPORT jint JNICALL
23.Java_org_danlley_jni_test_HelloJniTest_getDynamicIntData(JNIEnv *env,
jobject obj, jint i)
24.{
25. i*=i;
26. return i;
27.}
28.
29.JNIEXPORT jstring JNICALL
Java_org_danlley_jni_test_HelloJniTest_getDynamicStringData
30.(JNIEnv *env, jobject obj, jstring arg){
31. //Get the native string from javaString
32. const char *nativeString = env->GetStringUTFChars(arg, 0);
33. printf("%s", nativeString);
34. //DON'T FORGET THIS LINE!!!
35. env->ReleaseStringUTFChars(arg, nativeString);
36. return arg;
37.} // org_danlley_jni_test_HelloJniTest.cpp: implementation of
the org_danlley_jni_test_HelloJniTest class.
38.//
39.///////////////////////////////////////////////////////////////
///////
40.
41.#include "org_danlley_jni_test_HelloJniTest.h"
42.#include <jni.h>
43.#include <stdio.h>
44.
45.JNIEXPORT void JNICALL
46.Java_org_danlley_jni_test_HelloJniTest_displayHelloJni(JNIEnv
*env, jobject obj)
47.{
48. printf("Java_org_danlley_jni_test_HelloJniTest_displayHello
Jni has been called!n");
49. return;
50.}
51.
52.JNIEXPORT jint JNICALL
- 15. 53.Java_org_danlley_jni_test_HelloJniTest_getDynamicIntDataNoParam
(JNIEnv *env, jobject obj)
54.{
55. return 65535;
56.}
57.
58.JNIEXPORT jint JNICALL
59.Java_org_danlley_jni_test_HelloJniTest_getDynamicIntData(JNIEnv
*env, jobject obj, jint i)
60.{
61. i*=i;
62. return i;
63.}
64.
65.JNIEXPORT jstring JNICALL
Java_org_danlley_jni_test_HelloJniTest_getDynamicStringData
66.(JNIEnv *env, jobject obj, jstring arg){
67. //Get the native string from javaString
68. const char *nativeString = env->GetStringUTFChars(arg, 0);
69. printf("%s", nativeString);
70. //DON'T FORGET THIS LINE!!!
71. env->ReleaseStringUTFChars(arg, nativeString);
72. return arg;
73.}
重新对 C++工程打包成 dll 文件,运行结果:
---------------------------------------------------------------------------
tester.getDynamicIntDataNoParam()=65535
tester.getDynamicIntData(100)=10000
tester.getDynamicStringData=My first String test
Java_org_danlley_jni_test_HelloJniTest_displayHelloJni has been called!
My first String test
---------------------------------------------------------------------------
我们不仅把 Java 的一个 String 对象成功的传给了 dll,而且还将处理后的结果返回了出来。
但是总觉得还是不够,那我们就再来个比较复杂的对象把,我们这次将一个整形数组通过 java
传给 dll,看看是不是也可以处理,继续还是对 helloJniTest 类进行改造,新增一个方法:
Java 代码
1. package org.danlley.jni.test;
2.
3. public class HelloJniTest extends BaseClass {
- 16. 4. public HelloJniTest(String arg){
5. super(arg);
6. }
7. public native void displayHelloJni();
8.
9. public native int getDynamicIntDataNoParam();
10.
11. public native int getDynamicIntData(int i);
12.
13. public native String getDynamicStringData(String arg);
14.
15. public native int[] getDynamicArrayData(int[] args);
16.} package org.danlley.jni.test;
17.
18.public class HelloJniTest extends BaseClass {
19. public HelloJniTest(String arg){
20. super(arg);
21. }
22. public native void displayHelloJni();
23.
24. public native int getDynamicIntDataNoParam();
25.
26. public native int getDynamicIntData(int i);
27.
28. public native String getDynamicStringData(String arg);
29.
30. public native int[] getDynamicArrayData(int[] args);
31.}
重新生成 org_danlley_jni_test_HelloJniTest.h 文件
Cpp 代码
1. /* DO NOT EDIT THIS FILE - it is machine generated */
2. #include <jni.h>
3. /* Header for class org_danlley_jni_test_HelloJniTest */
4.
5. #ifndef _Included_org_danlley_jni_test_HelloJniTest
6. #define _Included_org_danlley_jni_test_HelloJniTest
7. #ifdef __cplusplus
8. extern "C" {
9. #endif
10./*
11. * Class: org_danlley_jni_test_HelloJniTest
12. * Method: displayHelloJni
- 17. 13. * Signature: ()V
14. */
15.JNIEXPORT void JNICALL
Java_org_danlley_jni_test_HelloJniTest_displayHelloJni
16. (JNIEnv *, jobject);
17.
18./*
19. * Class: org_danlley_jni_test_HelloJniTest
20. * Method: getDynamicIntDataNoParam
21. * Signature: ()I
22. */
23.JNIEXPORT jint JNICALL
Java_org_danlley_jni_test_HelloJniTest_getDynamicIntDataNoParam
24. (JNIEnv *, jobject);
25.
26./*
27. * Class: org_danlley_jni_test_HelloJniTest
28. * Method: getDynamicIntData
29. * Signature: (I)I
30. */
31.JNIEXPORT jint JNICALL
Java_org_danlley_jni_test_HelloJniTest_getDynamicIntData
32. (JNIEnv *, jobject, jint);
33.
34./*
35. * Class: org_danlley_jni_test_HelloJniTest
36. * Method: getDynamicStringData
37. * Signature: (Ljava/lang/String;)Ljava/lang/String;
38. */
39.JNIEXPORT jstring JNICALL
Java_org_danlley_jni_test_HelloJniTest_getDynamicStringData
40. (JNIEnv *, jobject, jstring);
41.
42./*
43. * Class: org_danlley_jni_test_HelloJniTest
44. * Method: getDynamicArrayData
45. * Signature: ([I)[I
46. */
47.JNIEXPORT jintArray JNICALL
Java_org_danlley_jni_test_HelloJniTest_getDynamicArrayData
48. (JNIEnv *, jobject, jintArray);
49.
50.#ifdef __cplusplus
51.}
52.#endif
53.#endif /* DO NOT EDIT THIS FILE - it is machine generated */
- 18. 54.#include <jni.h>
55./* Header for class org_danlley_jni_test_HelloJniTest */
56.
57.#ifndef _Included_org_danlley_jni_test_HelloJniTest
58.#define _Included_org_danlley_jni_test_HelloJniTest
59.#ifdef __cplusplus
60.extern "C" {
61.#endif
62./*
63. * Class: org_danlley_jni_test_HelloJniTest
64. * Method: displayHelloJni
65. * Signature: ()V
66. */
67.JNIEXPORT void JNICALL
Java_org_danlley_jni_test_HelloJniTest_displayHelloJni
68. (JNIEnv *, jobject);
69.
70./*
71. * Class: org_danlley_jni_test_HelloJniTest
72. * Method: getDynamicIntDataNoParam
73. * Signature: ()I
74. */
75.JNIEXPORT jint JNICALL
Java_org_danlley_jni_test_HelloJniTest_getDynamicIntDataNoParam
76. (JNIEnv *, jobject);
77.
78./*
79. * Class: org_danlley_jni_test_HelloJniTest
80. * Method: getDynamicIntData
81. * Signature: (I)I
82. */
83.JNIEXPORT jint JNICALL
Java_org_danlley_jni_test_HelloJniTest_getDynamicIntData
84. (JNIEnv *, jobject, jint);
85.
86./*
87. * Class: org_danlley_jni_test_HelloJniTest
88. * Method: getDynamicStringData
89. * Signature: (Ljava/lang/String;)Ljava/lang/String;
90. */
91.JNIEXPORT jstring JNICALL
Java_org_danlley_jni_test_HelloJniTest_getDynamicStringData
92. (JNIEnv *, jobject, jstring);
93.
94./*
95. * Class: org_danlley_jni_test_HelloJniTest
96. * Method: getDynamicArrayData
97. * Signature: ([I)[I
98. */
- 19. 99.JNIEXPORT jintArray JNICALL
Java_org_danlley_jni_test_HelloJniTest_getDynamicArrayData
100. (JNIEnv *, jobject, jintArray);
101.
102.#ifdef __cplusplus
103.}
104.#endif
105.#endif
改写 org_danlley_jni_test_HelloJniTest.cpp 文件:
Cpp 代码
1. // org_danlley_jni_test_HelloJniTest.cpp: implementation of the
org_danlley_jni_test_HelloJniTest class.
2. //
3. //////////////////////////////////////////////////////////////////////
4.
5. #include "org_danlley_jni_test_HelloJniTest.h"
6. #include <jni.h>
7. #include <stdio.h>
8.
9. JNIEXPORT void JNICALL
10.Java_org_danlley_jni_test_HelloJniTest_displayHelloJni(JNIEnv *env,
jobject obj)
11.{
12. printf("Java_org_danlley_jni_test_HelloJniTest_displayHelloJni has been
called!n");
13. return;
14.}
15.
16.JNIEXPORT jint JNICALL
17.Java_org_danlley_jni_test_HelloJniTest_getDynamicIntDataNoParam(JNIEn
v *env, jobject obj)
18.{
19. return 65535;
20.}
21.
22.JNIEXPORT jint JNICALL
23.Java_org_danlley_jni_test_HelloJniTest_getDynamicIntData(JNIEnv *env,
jobject obj, jint i)
24.{
25. i*=i;
26. return i;
27.}
- 20. 28.
29.JNIEXPORT jstring JNICALL
Java_org_danlley_jni_test_HelloJniTest_getDynamicStringData
30.(JNIEnv *env, jobject obj, jstring arg){
31. //Get the native string from javaString
32. const char *nativeString = env->GetStringUTFChars(arg, 0);
33. printf("%s", nativeString);
34. //DON'T FORGET THIS LINE!!!
35. env->ReleaseStringUTFChars(arg, nativeString);
36. return arg;
37.}
38.
39.
40.JNIEXPORT jintArray JNICALL
Java_org_danlley_jni_test_HelloJniTest_getDynamicArrayData
41.(JNIEnv *env, jobject obj, jintArray args){
42. jint buf[10];
43. jint i;
44. env->GetIntArrayRegion(args, 0, 10, buf);
45. jint j=0;
46. for (i = 0; i < 10; i++) {
47. j=buf[i];
48. j*=j;
49. buf[i]=j;
50. }
51. env->SetIntArrayRegion(args, 0, 10, buf);
52. return args;
53.} // org_danlley_jni_test_HelloJniTest.cpp: implementation of
the org_danlley_jni_test_HelloJniTest class.
54.//
55.///////////////////////////////////////////////////////////////
///////
56.
57.#include "org_danlley_jni_test_HelloJniTest.h"
58.#include <jni.h>
59.#include <stdio.h>
60.
61.JNIEXPORT void JNICALL
62.Java_org_danlley_jni_test_HelloJniTest_displayHelloJni(JNIEnv
*env, jobject obj)
63.{
64. printf("Java_org_danlley_jni_test_HelloJniTest_displayHello
Jni has been called!n");
65. return;
66.}
67.
68.JNIEXPORT jint JNICALL
- 21. 69.Java_org_danlley_jni_test_HelloJniTest_getDynamicIntDataNoParam
(JNIEnv *env, jobject obj)
70.{
71. return 65535;
72.}
73.
74.JNIEXPORT jint JNICALL
75.Java_org_danlley_jni_test_HelloJniTest_getDynamicIntData(JNIEnv
*env, jobject obj, jint i)
76.{
77. i*=i;
78. return i;
79.}
80.
81.JNIEXPORT jstring JNICALL
Java_org_danlley_jni_test_HelloJniTest_getDynamicStringData
82.(JNIEnv *env, jobject obj, jstring arg){
83. //Get the native string from javaString
84. const char *nativeString = env->GetStringUTFChars(arg, 0);
85. printf("%s", nativeString);
86. //DON'T FORGET THIS LINE!!!
87. env->ReleaseStringUTFChars(arg, nativeString);
88. return arg;
89.}
90.
91.
92.JNIEXPORT jintArray JNICALL
Java_org_danlley_jni_test_HelloJniTest_getDynamicArrayData
93.(JNIEnv *env, jobject obj, jintArray args){
94. jint buf[10];
95. jint i;
96. env->GetIntArrayRegion(args, 0, 10, buf);
97. jint j=0;
98. for (i = 0; i < 10; i++) {
99. j=buf[i];
100. j*=j;
101. buf[i]=j;
102. }
103. env->SetIntArrayRegion(args, 0, 10, buf);
104. return args;
105.}
改写 RunMain:
Java 代码
1. package org.danlley.jni.test;
- 22. 2.
3. public class RunMain {
4. public static void main(String[] args) {
5. HelloJniTest tester = new HelloJniTest("helloJniTest");
6. tester.displayHelloJni();
7. int i = tester.getDynamicIntDataNoParam();
8. System.out.println("tester.getDynamicIntDataNoParam()=" + i);
9. int j = tester.getDynamicIntData(100);
10. System.out.println("tester.getDynamicIntData(100)=" + j);
11. String str = tester.getDynamicStringData("My first String test");
12. System.out.println("tester.getDynamicStringData=" + str);
13. int[] args_int = new int[10];
14. for (int ii = 0; ii < 10; ii++) {
15. args_int[ii] = ii;
16. }
17. int[] args_arr = tester.getDynamicArrayData(args_int);
18. for (int ii = 0; ii < 10; ii++) {
19. System.out.println(args_arr[ii]);
20. }
21. }
22.} package org.danlley.jni.test;
23.
24.public class RunMain {
25. public static void main(String[] args) {
26. HelloJniTest tester = new HelloJniTest("helloJniTest");
27. tester.displayHelloJni();
28. int i = tester.getDynamicIntDataNoParam();
29. System.out.println("tester.getDynamicIntDataNoParam()="
+ i);
30. int j = tester.getDynamicIntData(100);
31. System.out.println("tester.getDynamicIntData(100)=" +
j);
32. String str = tester.getDynamicStringData("My first
String test");
33. System.out.println("tester.getDynamicStringData=" +
str);
34. int[] args_int = new int[10];
35. for (int ii = 0; ii < 10; ii++) {
36. args_int[ii] = ii;
37. }
38. int[] args_arr = tester.getDynamicArrayData(args_int);
39. for (int ii = 0; ii < 10; ii++) {
40. System.out.println(args_arr[ii]);
41. }
42. }
43.}