2010-12-04 3 views
1

У меня проблемы с чтением 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. 

ответ

1

Первое, что нужно отметить, что ArrayList! = Массив. Методы, используемые для доступа к массиву, работают только для массива.

Я предлагаю вам получить доступ к ArrayList, вызвав методы List так же, как и на Java.

+0

Спасибо, Питер, я понимаю эту точку ArrayList! = Array. Итак, вы предлагаете, я должен переработать полную функцию чтения и использовать метод Java get(), завернутый в JNI, чтобы прочитать все элементы? Мне просто интересно, почему все это работает до сих пор, но вложенный целочисленный массив этого не делает. – 2010-12-04 09:15:06

Смежные вопросы