Date: Sat, 25 Oct 97 15:58:57 JST From: SHUDOH Kazuyuki Subject: [JavaHouse-Brewers:13430] GC with native methods (Re: JNI cannot be implemented through RNI) To: java-house-brewers at center.nitech.ac.jp (JavaHouse Brewers ML) Message-Id: <199710250700.QAA25411@cafe.olu.info.waseda.ac.jp> 首藤です。 例によって、マニアック過ぎて一部の人向けの内容となっています。御容赦。 たなかさん wrote: たなか> nativeを実行している間は、gcが止まるのは、Sunのreference interpreterも たなか> そういう実装ではないですか? え゛、それってまじですか?と疑問を感じたので調べました。 JDK のソースを見ても、native なコード実行前に GC について 何かやっている様子はありません。で、実験しました。 Sun の JavaVM について次の結論に至りました。 (1) native method 実行中のスレッドがあっても GC は働く。 (2) native method で (C の変数で) 参照しているオブジェクトは 回収されない。(なんと!) 実験環境は JDK 1.1.3 for Linux Version 1 です。 JDK for Linux は、JDK for SunOS5 を Linux に port したものなので JDK for SunOS5 でも同じ結果が出ると推測します。 (2) については次のように想像しています。 native method の C のスタックフレームを走査し、 オブジェクト (のハンドル) と思しき値があれば、 そのオブジェクトは回収しない。 つまり、conservative GC してるんじゃないかと。 さすが Sun だなあ、と感心しました。 実験について説明します。 [実験 1] 調査内容: native method 実行中のスレッドがある時、GC は働くのか? 結果: 働く。 次の内容の native method を用意しました。 native method 中で作成したオブジェクトが回収されるかどうか調べます。 ===== JHandle *obj = NULL; obj = ObjAlloc(classJavaLangString, 0); /* オブジェクトを作成 */ obj のコンストラクタを呼ぶ; while (1) { javaStringPrint((Hjava_lang_String *)obj); /* System.out.print(String) と同等 */ usleep(100000L); /* 0.1 sec ポーズ, これで yield するはず */ sysThreadYield(); /* 念のためさらに yield */ } ===== % java -verbosegc クラス名 で実行しました。 native method 実行中のスレッドがあるにも関わらず GC は働いていました。 native method 中で作ったオブジェクトは回収されませんでした。 [実験 2] 調査内容: native method 中で作成されたオブジェクトは GC でどう扱われるのか? 結果: native method 中で C の変数に (ハンドルが) 代入されている オブジェクトは回収されない。 次の内容の native method を用意しました。 ===== #define ARRAY_SIZE 100 JHandle *objArray[ARRAY_SIZE]; int index = 0; while (1) { for (index = 0; index < ARRAY_SIZE; index++) { /* ObjAlloc(): オブジェクトの作成 */ #if 0 objArray[index] = ObjAlloc(classJavaLangString, 0); #else ObjAlloc(classJavaLangString, 0); #endif } } ===== 要はループボディの ObjAlloc() 近辺です。 ObjAlloc() で作成したオブジェクト (のハンドル) を、配 列 (JHandle *objArray[ARRAY_SIZE]) に代入する、しない、の 2つの場合で % java -verbosegc クラス名 と実行しました。なんとまあ、結果に差が出ました。 オブジェクト (のハンドル) を C の配列に代入 した場合: GC でオブジェクトはひとつも回収されない しない場合: GC で、前回の GC 後に作成されたオブジェクトが回収される つまり、オブジェクト (のハンドル) が native method 中の C の変数に 代入されていると、そのオブジェクトは GC で回収されません。 たなか> 色々考えると、Sunのやり方か、止めるかのどっちかしかない(:-)) たなか> とは思います。 Sun は C のスタックフレームを走査しての conservative GC で 乗り切っているように見えます。 とはいえ、世の中のあらゆる JavaVM にそれを期待するのは無茶なので、 JNI では local references を用意したのでしょうね。 Sun が自分の JavaVM のことだけを考えたならば local references は 不要でしょうが、やはり 特定の実装法を仮定しない仕様 (JNI) は必要 なので JNI を作ったのでしょうね。 あと、local references の利点として C のスタックフレームを走査するコストを省ける という点も考慮したかもしれません。 SHUDO Kazuyuki/首藤一幸 私をたばねないで あらせいとうの花のように shudoh at muraoka.info.waseda.ac.jp