- PR -

JNI のGetArrayLengthでNULLの値を渡すとどうなりますか?

投稿者投稿内容
tomomo
会議室デビュー日: 2003/06/05
投稿数: 7
お住まい・勤務地: 長野
投稿日時: 2004-12-27 15:10


tomomoです。お世話になります。

JNIを使って、次のようなコードを書きました。
この時、javaからjarybDataがNULLのデータを渡してしまうと、javaプロセスが
ダウンします。

ここで質問なのですが、GetArrayLengthにNULLのデータを渡してしまった場合、
どうなるのでしょうか?
私は、戻り値がNULLで値が帰ってくると思っていましたが、この認識が間違い
なのでしょうか?
javaがダウンするが正しい事で、きちんとNULLの判断をしてあがないといけな
いものなのでしょうか?

大変申し訳ございませんが、ご存知の方がいましたら教えてください。

以下、byte配列からcharに変換するC言語のコードです。

char* byteArray2char( JNIEnv* i_jEnv, jbyteArray jarybData, unsigned int *size)
{
char* cpData;
jsize jszArray;

jszArray = (*i_jEnv)->GetArrayLength( i_jEnv, jarybData );
if ( !jszArray ) return (char*)NULL;

cpData=(char *)malloc(jszArray+10);
if ( !(cpData) ) return (char*)NULL;

(*i_jEnv)->GetByteArrayRegion( i_jEnv, jarybData, 0, jszArray, (char *)cpData );
cpData[jszArray] = (char)NULL;

*size = jszArray;

return cpData;
}

tomomo
会議室デビュー日: 2003/06/05
投稿数: 7
お住まい・勤務地: 長野
投稿日時: 2004-12-27 15:15
tomomoです。

すみません、環境を書くのを忘れていました。

redhat ESL 3.0
java 1.4.2_06

です。
よろしくお願い致します。
H2
ぬし
会議室デビュー日: 2001/09/06
投稿数: 586
お住まい・勤務地: 港
投稿日時: 2004-12-27 16:19
うろ覚えですが、jsize はポインターではないので、GetArrayLengthはNULLを返す事はないと思います。調べてないので分かりませんが、-1とかを返しているのではないでしょうか。

ちなみに・・・
NULLは普通「0」なので、NULLの0と長さの0(空配列)が重なってしまうような値をGetArrayLengthは返さないはずです。
tomomo
会議室デビュー日: 2003/06/05
投稿数: 7
お住まい・勤務地: 長野
投稿日時: 2004-12-28 16:16
H2さん、返信ありがとうございます。
NULL値が返ってくるのも辺ですね。

ただ、次のようなプログラムを作ったのですが、
GetArrayLengthの引数がNULLだと、javaがハング
してしまうようです。

これが正しい動作なのか、ご存知の方がいましたら
教えてください。

<><><><>
# cat HelloJNI.java
public class HelloJNI{

public native void sayHello();

static{
System.loadLibrary("hellojni");
}

public static void main(String[] args){
HelloJNI hello = new HelloJNI();
hello.sayHello();
}
}

<><><><>

# cat HelloJNI.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloJNI */

#ifndef _Included_HelloJNI
#define _Included_HelloJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloJNI
* Method: sayHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloJNI_sayHello
(JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

<><><><>
# cat HelloJNI.c
#include "HelloJNI.h"

JNIEXPORT void JNICALL Java_HelloJNI_sayHello
(JNIEnv *env, jobject this)
{
jsize jszArray;
jbyteArray jarybData=NULL;

printf("Hello, JNI (Java Native Interface)...\n");
jszArray = (*env)->GetArrayLength( env, jarybData );
printf("Hello, JNI (Java Native Interface)...END\n");
}

<><><><>
上記のコードで、
# java HelloJNI
と実行すると、次の様にjavaがabortします。

Hello, JNI (Java Native Interface)...

Unexpected Signal : 11 occurred at PC=0xB722838C
Function=(null)
Library=/data/usr/local/j2sdk1.4.2_06/jre/lib/i386/client/libjvm.so

NOTE: We are unable to locate the function name symbol for the error
just occurred. Please refer to release documentation for possible
reason and solutions.


Current Java thread:
at HelloJNI.sayHello(Native Method)
at HelloJNI.main(HelloJNI.java:11)

Dynamic libraries:
08048000-08056000 r-xp 00000000 03:04 741616 /data/usr/local/j2sdk1.4.2_06/bin/java
08056000-08059000 rw-p 0000d000 03:04 741616 /data/usr/local/j2sdk1.4.2_06/bin/java
aa6f4000-aa6f5000 r-xp 00000000 03:02 1279426 /root/java_src/libhellojni.so
aa6f5000-aa6f6000 rw-p 00000000 03:02 1279426 /root/java_src/libhellojni.so
aa6f6000-aa7b2000 r--s 00000000 03:04 307046 /data/usr/local/j2sdk1.4.2_06/jre/lib/ext/localedata.jar
aa7b2000-aa7bf000 r--s 00000000 03:04 307015 /data/usr/local/j2sdk1.4.2_06/jre/lib/ext/ldapsec.jar
aa7bf000-aa7c2000 r--s 00000000 03:04 307013 /data/usr/local/j2sdk1.4.2_06/jre/lib/ext/dnsns.jar
aa7c2000-aa7de000 r--s 00000000 03:04 307012 /data/usr/local/j2sdk1.4.2_06/jre/lib/ext/sunjce_provider.jar
aa9e2000-aaabd000 r--p 00e76000 03:02 688180 /usr/lib/locale/locale-archive
aaabd000-aacbd000 r--p 00000000 03:02 688180 /usr/lib/locale/locale-archive
b4f6c000-b54c5000 r--s 00000000 03:04 194385 /data/usr/local/j2sdk1.4.2_06/jre/lib/charsets.jar
b54c5000-b54d6000 r--s 00000000 03:04 194340 /data/usr/local/j2sdk1.4.2_06/jre/lib/jce.jar
b54d6000-b55b3000 r--s 00000000 03:04 194384 /data/usr/local/j2sdk1.4.2_06/jre/lib/jsse.jar
b55b3000-b55c9000 r--s 00000000 03:04 194339 /data/usr/local/j2sdk1.4.2_06/jre/lib/sunrsasign.jar
b5613000-b6fba000 r--s 00000000 03:04 194387 /data/usr/local/j2sdk1.4.2_06/jre/lib/rt.jar
b6fba000-b6fce000 r-xp 00000000 03:04 226518 /data/usr/local/j2sdk1.4.2_06/jre/lib/i386/libzip.so
b6fce000-b6fd1000 rw-p 00013000 03:04 226518 /data/usr/local/j2sdk1.4.2_06/jre/lib/i386/libzip.so
b6fd1000-b6ff1000 r-xp 00000000 03:04 226516 /data/usr/local/j2sdk1.4.2_06/jre/lib/i386/libjava.so
b6ff1000-b6ff3000 rw-p 0001f000 03:04 226516 /data/usr/local/j2sdk1.4.2_06/jre/lib/i386/libjava.so
b6ff3000-b7003000 r-xp 00000000 03:04 226515 /data/usr/local/j2sdk1.4.2_06/jre/lib/i386/libverify.so
b7003000-b7005000 rw-p 0000f000 03:04 226515 /data/usr/local/j2sdk1.4.2_06/jre/lib/i386/libverify.so
b7005000-b7010000 r-xp 00000000 03:02 524378 /lib/libnss_files-2.3.2.so
b7010000-b7011000 rw-p 0000a000 03:02 524378 /lib/libnss_files-2.3.2.so
b701c000-b7020000 rw-s 00000000 03:02 1279427 /tmp/hsperfdata_root/6094
b7020000-b7041000 r-xp 00000000 03:02 1015865 /lib/tls/libm-2.3.2.so
b7041000-b7042000 rw-p 00020000 03:02 1015865 /lib/tls/libm-2.3.2.so
b7042000-b7054000 r-xp 00000000 03:02 524362 /lib/libnsl-2.3.2.so
b7054000-b7055000 rw-p 00011000 03:02 524362 /lib/libnsl-2.3.2.so
b705d000-b7065000 r-xp 00000000 03:04 226504 /data/usr/local/j2sdk1.4.2_06/jre/lib/i386/native_threads/libhpi.so
b7065000-b7066000 rw-p 00007000 03:04 226504 /data/usr/local/j2sdk1.4.2_06/jre/lib/i386/native_threads/libhpi.so
b7066000-b7462000 r-xp 00000000 03:04 226510 /data/usr/local/j2sdk1.4.2_06/jre/lib/i386/client/libjvm.so
b7462000-b747e000 rw-p 003fb000 03:04 226510 /data/usr/local/j2sdk1.4.2_06/jre/lib/i386/client/libjvm.so
b7491000-b75c2000 r-xp 00000000 03:02 1015863 /lib/tls/libc-2.3.2.so
b75c2000-b75c5000 rw-p 00130000 03:02 1015863 /lib/tls/libc-2.3.2.so
b75c8000-b75ca000 r-xp 00000000 03:02 524358 /lib/libdl-2.3.2.so
b75ca000-b75cb000 rw-p 00001000 03:02 524358 /lib/libdl-2.3.2.so
b75cb000-b75d8000 r-xp 00000000 03:02 1015867 /lib/tls/libpthread-0.60.so
b75d8000-b75d9000 rw-p 0000c000 03:02 1015867 /lib/tls/libpthread-0.60.so
b75eb000-b7600000 r-xp 00000000 03:02 524345 /lib/ld-2.3.2.so
b7600000-b7601000 rw-p 00015000 03:02 524345 /lib/ld-2.3.2.so

Heap at VM Abort:
Heap
def new generation total 576K, used 136K [0xaaec0000, 0xaaf60000, 0xab3a0000)
eden space 512K, 26% used [0xaaec0000, 0xaaee21c8, 0xaaf40000)
from space 64K, 0% used [0xaaf40000, 0xaaf40000, 0xaaf50000)
to space 64K, 0% used [0xaaf50000, 0xaaf50000, 0xaaf60000)
tenured generation total 1408K, used 0K [0xab3a0000, 0xab500000, 0xaeec0000)
the space 1408K, 0% used [0xab3a0000, 0xab3a0000, 0xab3a0200, 0xab500000)
compacting perm gen total 4096K, used 1171K [0xaeec0000, 0xaf2c0000, 0xb2ec0000)
the space 4096K, 28% used [0xaeec0000, 0xaefe4ff0, 0xaefe5000, 0xaf2c0000)

Local Time = Tue Dec 28 15:42:10 2004
Elapsed Time = 0
#
# HotSpot Virtual Machine Error : 11
# Error ID : 4F530E43505002EF
# Please report this error at
# http://java.sun.com/cgi-bin/bugreport.cgi
#
# Java VM: Java HotSpot(TM) Client VM (1.4.2_06-b03 mixed mode)
#
# An error report file has been saved as hs_err_pid6094.log.
# Please refer to the file for further information.
#
アボートしました


H2
ぬし
会議室デビュー日: 2001/09/06
投稿数: 586
お住まい・勤務地: 港
投稿日時: 2004-12-28 17:59
私も試してみました。GetArrayLengthにNULLを渡すとクラッシュするみたいですね。ドキュメントにはNULLを渡した場合どうなるか書いてないんですけどね。

ちなみに解決法は簡単です。

[code]
char* byteArray2char( JNIEnv* i_jEnv, jbyteArray jarybData, unsigned int *size)
{
char* cpData;
jsize jszArray;


//arrayがNULLならNULLを返す。
if (jarybData==NULL) return (char*)NULL;

jszArray = (*i_jEnv)->GetArrayLength( i_jEnv, jarybData );
if ( !jszArray ) return (char*)NULL;

cpData=(char *)malloc(jszArray+10);
if ( !(cpData) ) return (char*)NULL;

(*i_jEnv)->GetByteArrayRegion( i_jEnv, jarybData, 0, jszArray, (char *)cpData );
cpData[jszArray] = (char)NULL;

*size = jszArray;

return cpData;
}
tomomo
会議室デビュー日: 2003/06/05
投稿数: 7
お住まい・勤務地: 長野
投稿日時: 2004-12-28 18:20
H2さん。こんばんは。

そうですね。NULLチェックするのが良いのでしょうね。。
ありがとうございました。
Kissinger
ぬし
会議室デビュー日: 2002/04/30
投稿数: 428
お住まい・勤務地: 愛知県
投稿日時: 2004-12-28 21:21
H2様、
引用:
ドキュメントにはNULLを渡した場合どうなるか書いてないんですけどね。


Java Native Interface 仕様の『プログラミングエラーの報告』には
その理由も含めて明記されていますよ。
H2
ぬし
会議室デビュー日: 2001/09/06
投稿数: 586
お住まい・勤務地: 港
投稿日時: 2004-12-28 21:58
引用:

Kissingerさんの書き込み (2004-12-28 21:21) より:
H2様、
引用:
ドキュメントにはNULLを渡した場合どうなるか書いてないんですけどね。


Java Native Interface 仕様の『プログラミングエラーの報告』には
その理由も含めて明記されていますよ。


一応読んではいたのですが、そこで書かれている事はJNIで用意されている関数の事ではないと思います。あ、でも私の思い違いかもしれないです

http://java.sun.com/j2se/1.4.2/docs/guide/jni/spec/functions.html#wp17314
にはNULLの場合どうなるかは書いていません。できればこっちに書いてほしかったなぁ > Sun様

スキルアップ/キャリアアップ(JOB@IT)