Trouble 19: ヒープサイズが予期しない大きさになります
<Q19-1>ObjectOutputStream使用中にヒープ使用量が上がりつづけてしまいます。
| <発生環境> |
| OS |
Windows/Linux |
| JDK |
JDK1.3.1 |
| Vender |
Sun |
- <A19-1>
- ObjectOutputStream.writeObject()するとObjectOutputSream内に書き込まれたオブジェクトとそのオブジェクトが保持しているオブジェクトの参照がObjectOutputSream内にキャッシュとして保持されます。
この仕組みのため、自分のプログラムでは参照を開放したはずのオブジェクトがガベージコレクションの対象にならず、メモリを圧迫する場合があります。
ObjectOutputSreamを使用する場合はストリームを開いたままにせずに、適切なタイミングで閉じるか、ObjectOutputStream.reset()を呼び出してObjectOutputSreamが保持するオブジェクトの参照を開放する必要があります。
<Q19-2>Listのclear()を呼んでも空きヒープ領域が増えません。
空きヒープ領域を増やすために不要なListをclear()メソッドで開放しても、すぐには空きヒープ領域が増えません。
| <発生環境> |
| OS |
Any |
| JDK |
Any |
| Vender |
Any |
- <A19-2>
- Listのclear()メソッドはListが持っている参照を削除するだけであり、参照先のオブジェクトを破棄するわけではありません。そのため空きヒープ領域はすぐには増えません。
ガベージコレクトの実行により、参照先オブジェクトが使用していたヒープ領域が開放されます。
以下のサンプルを参照して下さい。
import java.util.*;
public class ListSample
{
public static void main(String[] args)
{
//プログラム開始時の空きヒープ領域を調べる。
Runtime rt = Runtime.getRuntime();
System.out.println( "\n<空きヒープ領域>\n");
System.out.println( "プログラム開始時\t: " + rt.freeMemory() );
//リストに格納するオブジェクトを用意する。
String[] bigObj = new String[100000];
for(int i=0; i<bigObj.length; i++)
{
bigObj[i] = "Now making a BIG object!!";
}
//オブジェクト作成後の空きヒープ領域を調べる。
System.out.println( "オブジェクト作成後\t: " + rt.freeMemory() );
//リストにオブジェクトを格納する。
ArrayList testList = new ArrayList();
for(int i=0; i<bigObj.length; i++)
{
testList.add( bigObj[i] );
}
//リスト作成後の空きヒープ領域を調べる。
System.out.println( "リスト作成後\t\t: " + rt.freeMemory() );
//リストからオブジェクトを削除する(ここでは参照が削除されるのみ)。
testList.clear();
//clear()呼び出し後の空きヒープ領域を調べる。
System.out.println( "clear()呼び出し後\t: " + rt.freeMemory() );
//ガベージコレクトを実行する。
System.gc();
//gc()呼び出し後の空きヒープ領域を調べる。
System.out.println( "gc()呼び出し後\t\t: " + rt.freeMemory() );
}
}
以下に実行結果を示します。
>java ListSample
<空きヒープ領域>
プログラム開始時 : 1757600
オブジェクト作成後 : 1357176
リスト作成後 : 594456
clear()呼び出し後 : 594136
gc()呼び出し後 : 1316264
clear()メソッドではヒープ領域の状態はほとんど変わらず、ガベージコレクトの実行後、空きヒープ領域が増えたことが分かります。
ただしgc()メソッドはJavaVMによっては実行されないことがあるので注意が必要です。

<Q19-3>tomcatの起動シェルでは起動オプションを指定していないのに、環境ごとに最大ヒープサイズが変わります。
環境A:
マシン : Sun Fire V490
メモリ : 8GB
CPU : ×4
⇒serverモード,最大ヒープサイズ=1024M
環境B:
マシン : Sun Fire V210
メモリ : 4GB
CPU : ×1
⇒clientモード,最大ヒープサイズ=64M
環境C:
マシン : Sun Fire V250
メモリ : 2GB
CPU : ×2
⇒serverモード,最大ヒープサイズ=512M
| <発生環境> |
| OS |
Any |
| JDK |
5.0 |
| Vender |
Sun |
注意:本文書の内容に誤りがあり、またこの文書によって不利益を被っても、
エスエムジー株式会社は一切関知いたしません。