再读斋

JNI之②头文件分析

编写Java文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class HeaderFile {
private native void doVoid();
native int doShort();
native void doArray(Object[] o );
native int doInt(int i); //byte ,short ,int,long,float,double ,boolean,char
native int doInt(double d); //byte ,short ,int,long,float,double ,boolean,char
native int doInt(Object o);
native int doInt(double d1,double d2);
static native int doInt(double d1 ,double d2,double d3);
static native int doInt(double d1 ,float f,boolean b ,char[] c );
native int doInt(int[] i);
native int doInt(int[] i1,double[] i2 );
static native int doInt(int[] i1,double[] i2 ,Object[] o );
public native String doString(String s);
public native Object doObject(Object o );
public native Enumeration doInterface(Iterator it);
public native Student doStudent(Student s);
// native int[] doInt(int[] i); //byte ,short ,int,long,float,double ,boolean,char
public native String[] doString(String[] s);
public native Object[] doObjects(Object[] o );
public native Enumeration[] doInterface(Iterator[] it);
public native Student[] doStudent(Student[] s);
public native static Object doAll(int[] i , String[] s , Student[] student );
}

生成头文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_nedu_jni_helloword_HeaderFile */
#ifndef _Included_com_nedu_jni_helloword_HeaderFile
#define _Included_com_nedu_jni_helloword_HeaderFile
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_nedu_jni_helloword_HeaderFile
* Method: doVoid
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_nedu_jni_helloword_HeaderFile_doVoid
(JNIEnv *, jobject);
/*
* Class: com_nedu_jni_helloword_HeaderFile
* Method: doShort
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_nedu_jni_helloword_HeaderFile_doShort
(JNIEnv *, jobject);
/*
* Class: com_nedu_jni_helloword_HeaderFile
* Method: doArray
* Signature: ([Ljava/lang/Object;)V
*/
JNIEXPORT void JNICALL Java_com_nedu_jni_helloword_HeaderFile_doArray
(JNIEnv *, jobject, jobjectArray);
/*
* Class: com_nedu_jni_helloword_HeaderFile
* Method: doInt
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_nedu_jni_helloword_HeaderFile_doInt__I
(JNIEnv *, jobject, jint);
/*
* Class: com_nedu_jni_helloword_HeaderFile
* Method: doInt
* Signature: (D)I
*/
JNIEXPORT jint JNICALL Java_com_nedu_jni_helloword_HeaderFile_doInt__D
(JNIEnv *, jobject, jdouble);
/*
* Class: com_nedu_jni_helloword_HeaderFile
* Method: doInt
* Signature: (Ljava/lang/Object;)I
*/
JNIEXPORT jint JNICALL Java_com_nedu_jni_helloword_HeaderFile_doInt__Ljava_lang_Object_2
(JNIEnv *, jobject, jobject);
/*
* Class: com_nedu_jni_helloword_HeaderFile
* Method: doInt
* Signature: (DD)I
*/
JNIEXPORT jint JNICALL Java_com_nedu_jni_helloword_HeaderFile_doInt__DD
(JNIEnv *, jobject, jdouble, jdouble);
/*
* Class: com_nedu_jni_helloword_HeaderFile
* Method: doInt
* Signature: (DDD)I
*/
JNIEXPORT jint JNICALL Java_com_nedu_jni_helloword_HeaderFile_doInt__DDD
(JNIEnv *, jclass, jdouble, jdouble, jdouble);
/*
* Class: com_nedu_jni_helloword_HeaderFile
* Method: doInt
* Signature: (DFZ[C)I
*/
JNIEXPORT jint JNICALL Java_com_nedu_jni_helloword_HeaderFile_doInt__DFZ_3C
(JNIEnv *, jclass, jdouble, jfloat, jboolean, jcharArray);
/*
* Class: com_nedu_jni_helloword_HeaderFile
* Method: doInt
* Signature: ([I)I
*/
JNIEXPORT jint JNICALL Java_com_nedu_jni_helloword_HeaderFile_doInt___3I
(JNIEnv *, jobject, jintArray);
/*
* Class: com_nedu_jni_helloword_HeaderFile
* Method: doInt
* Signature: ([I[D)I
*/
JNIEXPORT jint JNICALL Java_com_nedu_jni_helloword_HeaderFile_doInt___3I_3D
(JNIEnv *, jobject, jintArray, jdoubleArray);
/*
* Class: com_nedu_jni_helloword_HeaderFile
* Method: doInt
* Signature: ([I[D[Ljava/lang/Object;)I
*/
JNIEXPORT jint JNICALL Java_com_nedu_jni_helloword_HeaderFile_doInt___3I_3D_3Ljava_lang_Object_2
(JNIEnv *, jclass, jintArray, jdoubleArray, jobjectArray);
/*
* Class: com_nedu_jni_helloword_HeaderFile
* Method: doString
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_nedu_jni_helloword_HeaderFile_doString__Ljava_lang_String_2
(JNIEnv *, jobject, jstring);
/*
* Class: com_nedu_jni_helloword_HeaderFile
* Method: doObject
* Signature: (Ljava/lang/Object;)Ljava/lang/Object;
*/
JNIEXPORT jobject JNICALL Java_com_nedu_jni_helloword_HeaderFile_doObject
(JNIEnv *, jobject, jobject);
/*
* Class: com_nedu_jni_helloword_HeaderFile
* Method: doInterface
* Signature: (Ljava/util/Iterator;)Ljava/util/Enumeration;
*/
JNIEXPORT jobject JNICALL Java_com_nedu_jni_helloword_HeaderFile_doInterface__Ljava_util_Iterator_2
(JNIEnv *, jobject, jobject);
/*
* Class: com_nedu_jni_helloword_HeaderFile
* Method: doStudent
* Signature: (Lcom/nedu/jni/helloword/Student;)Lcom/nedu/jni/helloword/Student;
*/
JNIEXPORT jobject JNICALL Java_com_nedu_jni_helloword_HeaderFile_doStudent__Lcom_nedu_jni_helloword_Student_2
(JNIEnv *, jobject, jobject);
/*
* Class: com_nedu_jni_helloword_HeaderFile
* Method: doString
* Signature: ([Ljava/lang/String;)[Ljava/lang/String;
*/
JNIEXPORT jobjectArray JNICALL Java_com_nedu_jni_helloword_HeaderFile_doString___3Ljava_lang_String_2
(JNIEnv *, jobject, jobjectArray);
/*
* Class: com_nedu_jni_helloword_HeaderFile
* Method: doObjects
* Signature: ([Ljava/lang/Object;)[Ljava/lang/Object;
*/
JNIEXPORT jobjectArray JNICALL Java_com_nedu_jni_helloword_HeaderFile_doObjects
(JNIEnv *, jobject, jobjectArray);
/*
* Class: com_nedu_jni_helloword_HeaderFile
* Method: doInterface
* Signature: ([Ljava/util/Iterator;)[Ljava/util/Enumeration;
*/
JNIEXPORT jobjectArray JNICALL Java_com_nedu_jni_helloword_HeaderFile_doInterface___3Ljava_util_Iterator_2
(JNIEnv *, jobject, jobjectArray);
/*
* Class: com_nedu_jni_helloword_HeaderFile
* Method: doStudent
* Signature: ([Lcom/nedu/jni/helloword/Student;)[Lcom/nedu/jni/helloword/Student;
*/
JNIEXPORT jobjectArray JNICALL Java_com_nedu_jni_helloword_HeaderFile_doStudent___3Lcom_nedu_jni_helloword_Student_2
(JNIEnv *, jobject, jobjectArray);
/*
* Class: com_nedu_jni_helloword_HeaderFile
* Method: doAll
* Signature: ([I[Ljava/lang/String;[Lcom/nedu/jni/helloword/Student;)Ljava/lang/Object;
*/
JNIEXPORT jobject JNICALL Java_com_nedu_jni_helloword_HeaderFile_doAll
(JNIEnv *, jclass, jintArray, jobjectArray, jobjectArray);
#ifdef __cplusplus
}
#endif
#endif

头文件分析

方法注释

/*  
 * Class:     com_nedu_jni_helloword_HeaderFile  
 * Method:    doVoid  
 * Signature: ()V  
 */  

Class:表示Native方法的类名称
Method:表示方法名称
Signature:是方法的标识,主要提供我们再JNI操作java对象中使用

Signature一般 是两部分构成,一个方法的参数。另一个是返回类型。方法参数在括号里面,返回类型在后面,例如:

()V 

返回值为void,没有参数。

(DFZ[C)I 

返回值为int,参数为double、float、char[]

(Ljava/lang/String;)Ljava/lang/String;

返回值String,参数为String

  • 基本类型的对应关系如下

ALT TEXT

  • 方法参数或者返回值为java中的对象时,必须以“L”加上其路径,次路径必须以”/“分开,自定义的对象也使用本规则,不在包中时直接”L”,比如说java.lang.String为“java/lang/String”,com.nedu.jni.helloword.Student为”com/nedu/jni/helloword/Student”

  • 方法)方法参数或者返回值为数组时类型前加上[,例如[I表示int[],[[[D表示 double[][][],即几维数组就加几个[。例子如下:

ALT TEXT

方法的声明

1
JNIEXPORT void JNICALL Java_com_nedu_jni_helloword_HeaderFile_doArray(JNIEnv *,jobject,jobjectArray);

从声明可以看出方法基本由7部分组成:

  1. JNIEXPORT是JNI的关键字,表示此函数时要被JNI调用的
  2. void表示方法的返回值类型
  3. JNICALL是JNI的关键字,表示此函数时要被JNI调用的
  4. Java_为JNI中表示此方法来源于java的标志头
  5. com_nedu_jni_helloword_HeaderFile表示方法所在的包名+类名
  6. doArray表示方法名
  7. 参数:JNIEnv*是一个接口指针,用于定位函数表中的函数,后面的jobject是 一个指向该类的指针,类似与C语言中的this。这个第二个参数是变化的,当该方法为类的实例方法时该参数为jobject;当该方法为类方法(即静态方法)时该参数为jclass,指向该类的class。

根据不同方法前缀生成的头文件比较如下:

  • static与非static的比较

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    /* 非static方法
    * Class: com_nedu_jni_helloword_HeaderFile
    * Method: doInt
    * Signature: (DD)I
    */
    JNIEXPORT jint JNICALL Java_com_nedu_jni_helloword_HeaderFile_doInt__DD
    (JNIEnv *, jobject, jdouble, jdouble);
    /* static方法
    * Class: com_nedu_jni_helloword_HeaderFile
    * Method: doInt
    * Signature: (DDD)I
    */
    JNIEXPORT jint JNICALL Java_com_nedu_jni_helloword_HeaderFile_doInt__DDD
    (JNIEnv *, jclass, jdouble, jdouble, jdouble);
  • private、friendly、protected以及public这些方法限制符不会在JNI的头文件中出现。这些访问修饰符只有在其它类使用这些方法时有效!JNI中不关心此修饰符!

刘涤生 wechat