Date: Sat, 11 Sep 99 18:36:39 JST From: SHUDO Kazuyuki Subject: [JavaHouse-Brewers:27869] Re: asynchronous GC thread To: java-house-brewers at java-house.etl.go.jp (JavaHouse Brewers ML) Message-Id: <199909110934.SAA12039@cafe.muraoka.info.waseda.ac.jp> 首藤です。 > Classic VMのGCには,ヒープが不足した時にGCを起動せずにOutOfMemoryError > が発生することがあるという,アルゴリズム固有の問題が存在するのが知られ > ています. > > http://developer.java.sun.com/developer/bugParade/bugs/4055198.html このページでは、いくつかの問題(?)が混ざって議論されているように見えます。 (1) ヒープにはまだ余裕があるのに、 (オブジェクト用の領域ではなく) ハンドル用の領域のみが不足して OutOfMemoryError が発生してしまう。 (2) まだヒープに余裕があるはずなのに OutOfMemoryError が発生する。 (MemProblem.java のテスト) (JDK 1.2 で画像が異常な量のメモリを食う、というコメントが付いていますが、 それはこのバグレポートで述べられている JavaVM のメモリ管理の問題では ないように思います。 この問題は以前ここ (JHB) でも議論されたように思います。) (1) は当然起こり得ます。起こるようになっています。 (2) こそ、風間さんが問題にしたい点ですよね。 しかし再現させることが出来ませんでした。 [(1) について] Classic VM にはヒープの管理方式が 2通りあり、 JDK のコンパイル時に選択できるようになっています。 ページ (デフォルト 64KB) 単位で管理するか (paged heaps)、 連続した仮想記憶領域として確保するか (contiguous heaps)、です。 仮想記憶 (virtual memory) を持つ OS 上では contiguous heaps の方が 良いと私は考えます。実際、Solaris, Linux, FreeBSD 他の JDK は contiguous heaps の方を使っています。 JDK (Classic VM) のソースを調べると (*)、contiguous heaps の場合、 JDK 1.1.7 ではヒープの 25%、JDK 1.2.2 ではヒープの 20% を ハンドル専用の領域としていることが判ります。 (*) gc.c の InitializeAlloc0() (JDK 1.1.7), initializeAlloc0 (JDK 1.2.2)。 ハンドル用領域とオブジェクト用領域の割合 (25% : 75% or 20% : 80%) は 変更できません。どちらかが埋まっただけで OutOfMemoryError が発生します。 実際に、上記の報告 (Bug Id: 4055198) に添付されているテストコード MemProblem, Limit で、Classic VM を使って % java -verbosegc -mx4m MemProblem % java -verbosegc -mx4m Limit とすると、ハンドル用の領域が不足して OutOfMemoryError が発生します。 [(2) について] Bug Id: 4055198 では、MemProblem.java で稀に発生する、とありますが、 残念ながら (?) 僕の手もとでは再現させることができません… ヒープを 15MB (-mx15m) 以上確保すれば、OutOfMemoryError は発生しません。 Bug Id: 4055198 には JDK のメモリ管理コード gc.c へのパッチもあります。 しかしこのパッチを適用できる JDK が見つかりません。 97年 7月に作られたパッチなので JDK 1.1 の始めの頃かな、と思ったのですが、 JDK 1.0.2, 1.1.1, 1.1.5, 1.1.6, 1.1.7, 1.2.2 のどれにも適用できません。 パッチの中身は、1.0.2 より後に加えられた変更に対するもので、 1.1.1 の gc.c にはすでに適用されているように見えます。 > なお,このバグレポートでは1.2(というより,HotSpot VMでしょうね)には, > この問題は存在しないとコメントされています. はい。 おそらく、ハンドルを使わない種類の JVM では発生しない、という意味で 「1.2 (というより HotSpot VM) では発生しない」と 書いてあるのではないかと推測します。 > 私の研究プロジェクトでは,JDK 1.2のプロダクションリリースをメインに使っ > ていますが,どうもExact GCにも似たような問題があるようなのです. Exact VM (EVM) がどのようにヒープを管理しているのかは知らないです。 松岡研究室の人が EVM のソースコードを持っていたような。 プロダクションリリースの JVM も、HotSpot VM と同様に オブジェクトハンドルを廃していませんでしたっけ? (風間さんがそうおっしゃっていたような) > つまり,ヒープの最大値にまだ余裕があるにもかかわらず,GCも起こさずに, > ヒープも拡張せずにOutOfMemoryErrorが発生してしまうようなのです. > > かなりハードなテスト時において発生確率が0.1%以下ですので,気が付いてい > ない人も多いでしょう. 再現させるコードと条件をそろえるのが難しそうですね。 > Exact GCにも,このようなアルゴリズム上の問題がありそうなのか,それとも > 単なる実装ミスなのか,もし推測できることがあれば教えてください. 再現させることができていないので、 Classic VM のメモリ管理のどこに問題があるのかがまだわからないです。 それさえ判れば、EVM のコードを見て推測もできそうですが… JDK (Classic VM) のメモリ管理のコードをずいぶん読んでしまいました。 contiguous heaps の管理のために、mmap(2) のフラグ MAP_NORESERVE を 巧みに使っています。面白いです。 SHUDO Kazuyuki/首藤一幸 私をたばねないで あらせいとうの花のように shudoh at muraoka.info.waseda.ac.jp