publicclassArrayReader{ privatestaticnativeintsumArray(int[] arr); // 1 publicstaticvoidmain(String[] args){ // Array declaration int arr[] = newint[10]; // Fill the array for (int i = 0; i < 10; i++) { arr[i] = i; } ArrayReader reader = new ArrayReader(); // Call native method int result = reader.sumArray(arr); // 2 System.out.println("The sum of every element in the array is " + Integer.toString(result)); } static { System.loadLibrary("arrayreader"); } }
publicstaticvoidmain(String args[]){ InstanceAccess instanceAccessor = new InstanceAccess(); // Set the initial value of the name property instanceAccessor.setName("Jack"); System.out.println("Java: value of name = \""+ instanceAccessor.name +"\""); // Call the propetyAccess() method System.out.println("Java: calling propertyAccess() method..."); instanceAccessor.propertyAccess(); // 5 // Value of name after calling the propertyAccess() method System.out.println("Java: value of name after calling propertyAccess() = \""+ instanceAccessor.name +"\""); // Call the methodAccess() method System.out.println("Java: calling methodAccess() method..."); instanceAccessor.methodAccess(); // 6 System.out.println("Java: value of name after calling methodAccess() = \""+ instanceAccessor.name +"\""); }
/* Getting a reference to object class */ jclass class = (*env) -> GetObjectClass(env, object); /* 1 */
/* Getting the field id in the class */ fieldId = (*env) -> GetFieldID(env, class, "name", "Ljava/lang/String;"); /* 2 */ if (fieldId == NULL) { return; /* Error while getting field id */ }
/* From that jstring we are getting a C string: char* */ cString = (*env) -> GetStringUTFChars(env, jstr, NULL); /* 4 */ if (cString == NULL) { return; /* Out of memory */ } printf("C: value of name before property modification = \"%s\"\n", cString); (*env) -> ReleaseStringUTFChars(env, jstr, cString);
/* Creating a new string containing the new name */ jstr = (*env) -> NewStringUTF(env, "Brian"); /* 5 */ if (jstr == NULL) { return; /* Out of memory */ } /* Overwrite the value of the name property */ (*env) -> SetObjectField(env, object, fieldId, jstr); /* 6 */ }
JNIEXPORT void JNICALL Java_com_marakana_jniexamples_InstanceAccess_methodAccess(JNIEnv *env, jobject object){ jclass class = (*env) -> GetObjectClass(env, object); /* 7 */ jmethodID methodId = (*env) -> GetMethodID(env, class, "setName", "(Ljava/lang/String;)V"); /* 8 */ jstring jstr; if (methodId == NULL) { return; /* method not found */ } /* Creating a new string containing the new name */ jstr = (*env) -> NewStringUTF(env, "Nick"); /* 9 */ (*env) -> CallVoidMethod(env, object, methodId, jstr); /* 10 */ }
1 7 获取 class 对象的引用 2 从 class 对象中获取字段 Id,以及指定要获取的属性以及内部类型。可以从以下链接中获取关于 jni 类型的信息:http://download.oracle.com/javase/6/docs/technotes/guides/jni/spec/types.html 3 这里将会返回本地类型中的属性值 jstring 4 我们需要将 jstring 类型转换为 C 中的字符串 5 这里会创建出一个新的 java.lang.String 类型用以修改属性的值 6 将新的值设置给该属性 8 从先前获取到的 class 对象中通过方法的名称以及签名获取方法 id 。这里有一个用来获取方法签名的实用工具:javap -s -p ClassName for instance javap -s -p InstanceAccess 9 创建出一个新的 java.lang.String 对象作为从本地代码调用 java 方法的参数。 10 由于 Java 方法返回值类型为 void,所以调用 CallVoidMethod 方法,并且将先前创建出的 jstring 作为参数传递给它