【问题标题】:jvm crash on reading arraylist from java class with jnijvm在使用jni从java类读取arraylist时崩溃
【发布时间】:2010-12-04 08:33:20
【问题描述】:

我在使用 jni 从 java 类中读取数组列表时遇到问题。在java类中,arraylist是这样定义的

public static List XTN_STC_search_result = new ArrayList();

然后,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 条目、标签字符串、双精度值,并且可以使用嵌套循环访问整数数组。在嵌套循环中,如果使用 getObjectArrayElement 获取整数数组条目,它似乎获得了该值。之后我在 NULL 上测试它,它不是 NULL。为了迂腐,我再次检查该数组条目(整数数组的)是否是带有 isInstanceOf 的 Integer 实例。那个调用使我的程序因 SIGSEGV 和 JVM 退出而崩溃。

下面看问题区域的代码sn-p ...

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 reader函数的代码sn-p足够完整,可以理解我的问题。也许有人可以指出我在这个问题上的正确方向,希望:-))

我用 JRE 版本:6.0_22-b04 Java 虚拟机:Java HotSpot(TM) 64 位服务器虚拟机(17.1-b03 混合模式 linux-amd64 ) 在 Ubuntu 上

非常感谢您在此帮助我。

2010/12/06 更新: =================== 正如彼得建议的那样,我使用 对象的Java 方法通过本机接口。另外它 原来,我什至不需要我构建的那个数组列表 Java类,我宁愿使用并阅读内部类Results Object List 直接和它的对象方法来读取我需要的结果。所以简而言之, 现在效率更高了,我可以跳过 Arraylist 构造 完成并节省一个处理步骤。 首先我想,通过 JNI 使用该类的 Java 方法会 给我一个更高的响应时间,通过 JNI 使用 Java 方法肯定是 不是很快(与直接在 Java 中使用 Java 方法相比)。使用 JNI 作为从 C 到 Java 的桥梁会消耗性能和计算时间。但无论如何,我 想通了,我比旧的快 200 毫秒(使用相同的数据集) 读取器方法与arraylist,所以我什至获得了一些性能。 好的,简单来说就是使用JNI和Java类的Object方法 让我省了很多麻烦,现在的代码更具可读性。 结论:我想鼓励所有面临类似情况的人 使用您通过 JNI 使用的类的 Object 方法时出现问题。

【问题讨论】:

    标签: java c crash jvm java-native-interface


    【解决方案1】:

    首先要注意的是 ArrayList != 一个数组。您用于访问数组列表的方法仅适用于数组。

    我建议您通过调用 List 的方法来访问 ArrayList,就像在 Java 中一样。

    【讨论】:

    • 谢谢彼得,我明白 ArrayList != Array.所以你建议,我应该重新编写完整的阅读器功能并使用 JNI 包装的 Java“get()”方法来读取所有元素?我只是想知道为什么到目前为止它都起作用,但嵌套整数数组却没有。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-19
    • 2013-09-12
    • 2019-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多