jvm crash on reading arraylist from java class with jni
I have troubles reading an arraylist from a java class with jni. In the java class the arraylist is defined like this
public static List XTN_STC_search_result = new ArrayList();
The arraylist then gets filled with a string, a score value as double and an array of integers.
So the structure looks like this:
[
[label str 1, score value 1, [int 1, int 2, int n]],
[label str 2, score value 2, [int 1, int 2],
...
]
On the JNI C side i do the following to read that arraylist.
After reading the static field and get the object I go into the loop iterating over the array to read all values. All goes well, I can read every single arraylist entry, the label string, the double value and can access the array of integers with a nested loop. Within the nested loop if fetch the integer array entry with getObjectArrayElement and it seems to get that value. Afterwards I test it on NULL and it is not NULL. To be pedantic I I double check if that array entry (of the integer array) is an instance of Integer with isInstanceOf. That very call crashes my program with SIGSEGV and JVM bails out.
Below you see the code snippet of the problemtic area ...
int
XTN_ce_java_get_cluster(XTN_VM_IDX vm_idx) {
...
/* java result object , the arraylist to read */
jobjectArray result_obj;
/* result object array (element of result_obj) */
jobjectArray jv_result_object_array;
jint jv_result_object_array_size;
/* element to hold phrase, score and nested integer array */
jobject jv_ob开发者_StackOverflow社区ject_array_cluster_elem;
jint jv_object_array_cluster_elem_size;
...
/* get arraylist */
jv_result_object_array = (*(Record.env))->GetObjectArrayElement(
Record.env, result_obj, 1 );
jv_result_object_array_size = (*(Record.env))->GetArrayLength(Record.env,
jv_result_object_array );
...
/* loop over arraylist entries */
for (i = 0; i < jv_result_object_array_size; i++) {
/* read label string */
if ( (*(Record.env))->IsInstanceOf(Record.env,
(jobject)jv_object_array_cluster_elem, classString)) {
...
} else if ( (*(Record.env))->IsInstanceOf(Record.env, jv_object_array_cluster_elem, classObject)) {
/* we are about to read the integer array from the arraylist ... */
/* get size of integer array */
jv_object_array_cluster_elem_size = (*(Record.env))->GetArrayLength(
Record.env, jv_object_array_cluster_elem);
/* this case should not happen, the integer array has a minimum entry of 1 element */
if (jv_object_array_cluster_elem_size <= 0)
continue;
for (j = 0; j < jv_object_array_cluster_elem_size; j++) {
/* get element from integer array */
jv_cluster_data_array_elem = (*(Record.env))->GetObjectArrayElement(
Record.env, jv_object_array_cluster_elem, j);
/* check if null */
if (jv_cluster_data_array_elem == NULL) {
break;
/* now check type */
/* THIS CALL CRASHES JVM */
if ( (*(Record.env))->IsInstanceOf(Record.env, jv_cluster_data_array_elem,
classInteger)) {
fprintf(stdout, "got array entry of type integer */
}
...
} /* inner loop integer array */
} /* outer loop object array */
return 1;
}
I do not understand why it crashes there, even though I seem not to be able to access that field for reading (with GetIntField() for example). If I leave out the isInstanceOf call (just looping over the integer array) all goes fine, it loops over the complete arraylist, reads my strings and doubles, loops over the nested integer array and finishes successfully. Honestly the
Does anybody have a hint for me where to look or what to improve? I hope the provided code snippet of the arraylist reader function is complete enough to understand my problem. Maybe somebody can point me to the right direction on this issue, hopefully :-))
I use JRE version: 6.0_22-b04 Java VM: Java HotSpot(TM) 64-Bit Server VM (17.1-b03 mixed mode linux-amd64 ) on Ubuntu
Thanks so much in advance for helping me out on this.
Update 2010/12/06: ================== As Peter suggested, I completely reworked the object reader function using the Java methods of the object through the native interface. Additionally it turned out, that I even do not need that very arraylist I constructed in the Java class, I rather used and read the internal class Results Object List directly and its object methods to read the results I need. So in short, now it is more efficient and I was able to skip that Arraylist construction completey and spare one processing step. First I thought, using the Java methods of that very class through JNI would give me a much higher response time, using Java methods through JNI is surely not very fast (compared to using the Java methods in Java directly). Using JNI as a bridge from C to Java costs performance and computing time. But anyway, I figured out, I am about 200ms faster (using the same data set) than my old reader method with the arraylist, so I even gained some performance. Ok, to put it in short, using JNI and the Object methods of the Java class spared me a lot of headache and the code now is much more readable. Conclusion: I would like to encourage everybody that is facing a similar problem using the Object methods of the class you work with through JNI.
The first thing to note is that ArrayList != an array. The methods you are using to access the arraylist only work for an array.
I suggest you access the ArrayList by calling the methods of the List just as you would in Java.
精彩评论