У меня проблемы с чтением arraylist из java-класса с jni. В классе Java ArrayList определяется как этотjvm crash при чтении arraylist из класса java с jni
public static List XTN_STC_search_result = new ArrayList();
The ArrayList затем наполняется строка, значение бальной как двойной и массив целых чисел. Так структура выглядит следующим образом:
[
[label str 1, score value 1, [int 1, int 2, int n]],
[label str 2, score value 2, [int 1, int 2],
...
]
На стороне JNI C я делаю следующее, чтобы прочитать, что ArrayList.
После прочтения статического поля и получения объекта я перехожу в цикл, итерации по массиву, чтобы читать все значения. Все идет хорошо, я могу прочитать каждую запись arraylist, строку метки, двойное значение и получить доступ к массиву целых чисел с вложенным циклом. Внутри вложенного цикла, если выборка целочисленного элемента массива с getObjectArrayElement и, похоже, получает это значение. Впоследствии я тестирую его на NULL, и это не NULL. Чтобы быть педантичным, я дважды проверяю, является ли эта запись массива (целочисленного массива) экземпляром Integer с isInstanceOf. Этот вызов вызывает сбои в моей программе с помощью SIGSEGV и JVM.
Ниже вы видите фрагмент кода в problemtic области ...
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_object_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;
}
Я не понимаю, почему он падает там, хотя я, кажется, не быть в состоянии получить доступ к этому полю для чтения (с GetIntField() например). Если я оставил вызов isInstanceOf (просто цикл по целочисленному массиву), все идет хорошо, он перебирает полный аррайалист, читает мои строки и удваивает, петли над вложенным целым массивом и успешно завершается. Честно говоря,
Есть ли у кого-нибудь намек на меня, где искать или что улучшить? Я надеюсь, что предоставленный фрагмент кода функции считывателя arraylist будет достаточно полным, чтобы понять мою проблему. Может быть, кто-то может мне точку в правильном направлении по этому вопросу, надеюсь :-))
Я использую JRE версии: 6.0_22-b04 Java VM: Java HotSpot (TM) 64-разрядного сервера VM (17,1-B03 смешанный режим linux-amd64) на Ubuntu
Большое спасибо за то, что помогли мне в этом.
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.
Спасибо, Питер, я понимаю эту точку ArrayList! = Array. Итак, вы предлагаете, я должен переработать полную функцию чтения и использовать метод Java get(), завернутый в JNI, чтобы прочитать все элементы? Мне просто интересно, почему все это работает до сих пор, но вложенный целочисленный массив этого не делает. – 2010-12-04 09:15:06