2010-12-04 5 views
1

jniでjavaクラスからarraylistを読み込む際に問題があります。 JavaクラスのArrayListのは、文字列、ダブルとしてスコア値と整数の配列で満たされます。このjvmクラッシュでJavaクラスからjarでJavaクラスから

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], 
    ... 
]

私は、このarraylistを読むために以下を行います。

静的フィールドを読み込んでオブジェクトを取得した後、配列全体をループしてすべての値を読み込みます。すべてうまく行く、私はすべての単一のarraylistエントリ、ラベル文字列、二重の値を読み取ることができ、ネストされたループで整数の配列にアクセスすることができます。ネストされたループ内でgetObjectArrayElementを使用して整数配列エントリを取得すると、その値が取得されるようです。その後、私はNULLでそれをテストし、それはNULLではありません。ペダンティックであるためには、(整数配列の)配列エントリがisInstanceOfを持つIntegerのインスタンスであるかどうかを再確認します。 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をループし、文字列と倍精度を読み込み、ネストされた整数配列をループして正常に終了します。正直には

誰かが私のためにヒントを見たり、改善すべき点はありますか?私はarraylistリーダー関数の提供されたコードスニペットが私の問題を理解するのに十分であることを願っています。 6.0_22-B04 のJava VM::は、Java HotSpot(TM)64ビットサーバーVM(17.1-B03たぶん誰かが)うまくいけば:-)、この問題に正しい方向に私は JREバージョンを使用

私を指すことができます混在モードlinux-amd64) on 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にアクセスするために使用しているメソッドは、配列に対してのみ機能します。

Javaの場合と同じように、リストのメソッドを呼び出すことによってArrayListにアクセスすることをお勧めします。

+0

感謝のピーター、私はその点を理解ArrayList!=配列。だからあなたは、私は完全なリーダー関数を修正し、すべての要素を読み取るためにJNIでラップされたJavaの "get()"メソッドを使用することをお勧めしますか?私はなぜこれまでにすべての関数が機能しているのか疑問に思っています。 –

関連する問題