2 static jfieldID id_a;
3 ...
4 if (class_X == 0) {
5 jclass cx = env->GetObjectClass(obj);
6 class_X = env->NewGlobalRef(cx);
7 id_a = env->GetFieldID(env,cls,"a","...");
8 }
然而需要注意的是,在结束对类的使用时,务必调用:env->DeleteGlobalRef(class_X)来通知JVM释放该资源。
3) 含有main函数的调用测试代码:
1 public class MyTest {
2 public static void main(String[] args) throws Exception {
3 Employee[] staff = new Employee[3];
4 staff[0] = new Employee("Harry Hacker",35000);
5 staff[1] = new Employee("Carl Cracker",75000);
6 staff[2] = new Employee("Tony Tester",38000);
7 for (Employee e : staff)
8 e.raiseSalary(5);
9 for (Employee e : staff)
10 e.print();
11 }
12 }
13 /* 输出结果如下:
14 Harry Hacker 71750.0
15 Carl Cracker 153750.0
16 Tony Tester 77900.0
17 */
7. 编码签名:
为了访问实例域和调用Java编程语言中定义的方法,你必须学习"编入"数据类型的名称和方法签名的规则,见如下编码方案:
B byte
C char
D double //如下例中env->GetFieldID(class_Employee,"salary","D");
F float
I int
J long
S short
V void
Z boolean
Lclassname; 类的类型
如果描述数组类型,需要使用[,如果二维数组[[,以此类推。如:
[Ljava/lang/String; //String一维数组
[[F //float[][]二维数组
要建立一个方法的完整签名,需要把括号内的参数类型都列出来,然后列出返回值类型,如:
(II)I //一个接收两个整型参数并返回一个整数的方法编码。
上例中的print方法的签名是:(Ljava/lang/String;)V //表示该方法接收一个字符串String参数,返回值为void。
注意,在L表达式结尾处的分号是类型表达式的终止符,而不是参数之间的分隔符,如上例中Employee的构造函数:
Employee(java.lang.String,double,java.util.Date); 具有如下签名:
(Ljava/lang/String;DLjava/util/Date;)V
可以看到在D和Ljava/util/Date;之间没有分隔符。另外要注意在这个编码方案中,必须用/代替.来分隔包名和类名。结尾的V表示返回类型为void。即使对Java的构造器没有指定返回类型,也需要将V添加到JVM签名中。
8. 调用Java非静态方法:
Java中可以通过JNI调用native的C语言方法,同样JNI也提供了方法可以让C语言中的方法调用Java的方法,见下例:
1) 包含native方法的Java类代码:
1 import java.io.PrintWriter;
2 public class Printf {
3 public static native void fprint(PrintWriter out,String format,double x);
4 static {
5 System.loadLibrary("Printf");
6 }
7 }
2) 实现本地方法的C语言代码:
1 #include "Printf.h"
2 #include
3 #include
4 #include
5
6 JNIEXPORT void JNICALL Java_Printf_fprint
7 (JNIEnv* env, jclass cl, jobject out, jstring format, jdouble x)
8 {
9 const char* cformat = env->GetStringUTFChars(format,NULL);
10 char* cstr = (char*)calloc(strlen(cformat) + 20,sizeof(char));
11 sprintf(cstr,cformat,x);
12 jstring str = env->NewStringUTF(cstr);
13 free(cstr);
14 env->ReleaseStringUTFChars(format,cformat);
15
16 jclass class_PrintWriter = env->GetObjectClass(out);
17 //对应于void PrintWrite.print(String)方法
18 jmethodID id_print = env->GetMethodID(class_PrintWriter,"print","(Ljava/lang/String;)V");
19 //这里Void是CallXxxMethod一组方法中的一个,表示调用函数的返回值类型。
20 //因此该方法的返回值也是void,如果调用CallIntMethod,其返回值将为jint。
21 env->CallVoidMethod(out,id_print,str);
22 }
3) 含有main函数的调用测试代码:
1 import java.io.PrintWriter;
2 public cla