メモリの確保とgcについて

このQ&Aのポイント
  • GC(ガベージコレクション)のタイミングや判断基準に関する話題です。
  • 2つのクラスの実行結果の違い、特にメモリの確保の違いについて疑問があります。
  • WindowsXPの実行環境でエクリプスを使用しています。メモリはデフォルトの64MBです。
回答を見る
  • ベストアンサー

メモリの確保とgcについて?

gcのタイミングとか、その判断基準の話になるのかもしれません。下記の2つのクラスの実行結果の違いがなぜおきるのかわかりません。 理解できる方、解説お願いします。 WindowsXPでエクリプス上で実行しています。実行時のメモリはデフォルトの64MBのままです。 コンパイラ実行環境は1.4系です。 ●テスト・クラス変数1、結果 ◆VM 確保Total:17MB ◆VM 確保Total:44MB ◆VM 確保Total:46MB ◆VM 確保Total:46MB ◆VM 確保Total:46MB ◆VM 確保Total:46MB ●テスト・クラス変数2、結果 ◆VM 確保Total:33MB java.lang.OutOfMemoryError Exception in thread "main" 全部張ると800文字を超えてしまうのでソースの一部のみを記述します。 // クラス変数として宣言、両クラスで共通 private static HashMap map; // テスト・クラス変数1 // mainメソッド中でこの記述が6回記述 map = new HashMap(4000000); map.put("1", "いちご"); System.out.println("◆VM 確保Total:" + Runtime.getRuntime().totalMemory() / 1024 / 1024 + "MB"); // テスト・クラス変数2 // mainメソッド中でこの記述が4回記述 map = new HashMap(5000000); map.put("1", "いちご"); System.out.println("◆VM 確保Total:" + Runtime.getRuntime().totalMemory() / 1024 / 1024 + "MB");

  • Java
  • 回答数1
  • ありがとう数2

質問者が選んだベストアンサー

  • ベストアンサー
  • rinkun
  • ベストアンサー率44% (706/1571)
回答No.1

> map = new HashMap(5000000); このコードの動作を見てみましょう。 まず5000000エントリのHashMapが作られ、それからmapに代入されます。mapに以前あったオブジェクトは代入の際にゴミになり、GC対象となります。 要するに少なくとも2つのHashMap(5000000)が存在できるだけのメモリが必要です。 次に > ●テスト・クラス変数1、結果 > ◆VM 確保Total:17MB と > ●テスト・クラス変数2、結果 > ◆VM 確保Total:33MB に注目します。 HashMapのマップサイズは指定したエントリ数そのままではなく倍に増えています。2冪に切り上げしているのかもしれません。 これらから、後半のテストで2回目のHashMap作成には少なくとも66MB以上のメモリを必要とするだろうことが分かります。 メモリは64MBしかありませんからOutOfMemoryErrorになります。

arakororin
質問者

お礼

あ、そうか。そうですね。 次のインスタンスがnewされて前のオブジェクトの参照が…とかの問題ですね。 参考になりました。ありがとうございました。 ちなみにVM確保だけではメモリの実使用状況はわからないので、下記のメソッドで確認したところ、 4194304までが16.0MB、4194305以上が32.0MBでした。 private static void メモリ表示する() { System.gc(); double VM確保 = Runtime.getRuntime().totalMemory() / 1024 / 1024; double VM実使用 = VM確保 - Runtime.getRuntime().freeMemory() / 1024 / 1024; System.out.println("◆VM確保:" + VM確保 + "MB ◆VM実使用:" + VM実使用 + "MB"); }

関連するQ&A

  • C言語のメモリ領域確保

    ポインタ変数ををmain関数で宣言し、関数test()にて必要分だけ領域確保してそのアドレスをmain関数のポインタ変数に渡して利用することは可能でしょうか。 (サイズのわからないテキストデータを、十分に大きな配列に入れるのではなく、関数でメモリを動的確保して無駄の無い配列に入れたい等) C言語ではやはり無理で、構造体のリストにするのが一番でしょうか。 初歩的なことで申し訳ありませんがどなたかお願いいたします。

  • 例えば、以下のようなクラスでmap変数に、あらかじめ値を入れておいて、

    例えば、以下のようなクラスでmap変数に、あらかじめ値を入れておいて、別のクラスで使うときに Common.map.get(""); と書いて、いつでも値を取り出したいのですが、static変数は、コンストラクタでいじれないようで出来ません。 このCommonクラス内であらかじめ値を入れておく方法はあるでしょうか? public class Common{ public static HashMap<String, String> map = new HashMap(); }

    • ベストアンサー
    • Java
  • Tomcatのクラスパス

    OSの環境変数で指定したclasspathと Tomcatのクラスパスは違うようですが、 Tomcatの場合web.xmlに記述するのでしょうか? 1つのjavaクラスを、サーブレットから、 Runtime.getRuntime().exec() で実行したい場合、Tomcatのweb.xmlなどにクラスパスを指定するのでなく、-classpathを指定した方が良いのでしょうか?

    • ベストアンサー
    • Java
  • ネットワーク上の他のパソコン内のjarを実行したい。

    ネットワーク上の他のパソコン内のjarを実行したい。 実行して他のパソコンの中で動かしたいですが、反応がありませんでした。 他のパソコン側のセキュリティ設定や、jarファイルへの設定が必要なのでしょうか。 また、他の方法で同じことはできませんでしょうか。 ご存知の方がおられましたら教えてください。 よろしくお願いいたします。 以下は、試したソースです。 import java.io.IOException; public class exec { public static void main(String[] args) { // ネットワーク上のjarを実行したい。 try { //Runtime.getRuntime().exec("cmd /c start //myPC/log/test.jar");//反応なし //Runtime.getRuntime().exec("cmd /c start //myPC/log/test.txt");//反応なし Runtime.getRuntime().exec("cmd /c start C:/log/test.jar");//実行できる Runtime.getRuntime().exec("cmd /c start C:/log/test.txt");//実行できる } catch (IOException e) { e.printStackTrace(); } } }

    • ベストアンサー
    • Java
  • JUnitのテストメソッドごとのメモリの確保とかの話

    JUnit関連の少しコアな話になります。 JUnitではデフォルトでは、実行する際初期処理としてまずテストクラス内のテストメソッドの数だけテストクラスをインスタンス化し、その後各テストメソッドを実行していく、という仕様になっているようです。そしてかつ、各インスタンスはテストクラス内のすべてのテストメソッドが終了するまでインスタンスの破棄は行わないようです。 上記の仕様であるはずだと言う根拠は、テストクラスにコンストラクタを作成し、そこにsysoutを記述することにより確認をしました。 上記の仕様であることが主原因で、Out of Memoryが発生してしまいます。 他にそうなってしまう原因はいくつかあって ・Springを利用していて初期化にメモリを結構使う ・テスト対象のクラスが複雑でテストメソッドの数が多くなる ・パソコンの物理メモリに限界がある ・DJUnitでカバレッジを調査することもあり、またテスティングペアの名前は統一したいので、テスト対象クラスとテストクラスを1対1に対応させたい。 などが挙げられます。VMの実行メモリを大きくしたり、テストクラスを分割してしまうなどの対処療法を行ってきましたが、何とか主原因をつぶす方法は無いものかと質問をした次第です。 (その他、使用しなくなったオブジェクトにnullをセットしたり明示的にgcの実行を指示する等の苦肉の策を行いましたが、ほとんど影響しませんでした) 前置きが長くなりましたが質問は、JUnitでテストを行う際、テストクラス内のテストメソッドの数だけインスタンス化しているものを、あるテストメソッドを実行する直前にインスタンス化し、そのテストメソッドが終了したらそのインスタンスを破棄するような設定はないのか、あればその方法を教えてほしい、ということになします。 だいぶ分かりにくい説明かもしれませんが…。 以上よろしくお願いします。

    • ベストアンサー
    • Java
  • Appletへの変換の仕方

    public class Test { public static void main(String[] arg) throws Exception{ Runtime rt = Runtime.getRuntime(); //Runtimeオブジェクトの取得 rt.exec("Capture2004.exe"); //実行 } } 上記のプログラムをブラウザ上で活用したいので、Appletに直したいのですが、throws Exceptionの使い方がわからず困っています。 変換の仕方がわかる方がいましたら、御指導をお願いいたします。

  • ArrayListとHashMapを利用する問題について

    『問題』 (1)ArrayListのオブジェクトを生成する。 (2)「何回入力しますか?」と出力し、入力処理を行う。 (3)(2)で入力された回数分、以下の処理を行う。   1)HashMapのオブジェクトを生成する。   2)「名前を入力して下さい。」と出力し、入力処理を行う。 3)「性別を入力して下さい。」と出力し、入力処理を行う。   4)「性別を入力して下さい。」と出力し、入力処理を行う。 5) 1)で作成したHashMapに、それぞれ入力された 名前・年齢・性別を設定する。   6)値を設定したHashMapを(1)で作成したArrayListへ格納する。 (4)ArrayListの件数分、以下の処理を行う。   1)ArrayListより、HashMapを取得する。   2)取得したHashMapより、それぞれ設定されている 名前・年齢・性別を取得する。   3)HashMapより取得した名前・年齢・性別を出力する。 『実行結果』 何回入力しますか? 2 名前を入力して下さい。 iwata 年齢を入力して下さい。 27 性別を入力して下さい。 men 名前を入力して下さい。 hana 年齢を入力して下さい。 21 性別を入力して下さい。 women 名前=iwata 年齢=27 性別=men 名前=hana 年齢=21 性別=women 上記のようなプログラムを書く問題について質問します。 (3)までは自力で書けて実行結果もこの通りになったのですが、 (4)が分からずに、実行結果では値の部分がnullと出力されて しまいました。自分でもこの記述は間違っているというのは感じる のですが、どうしたら値がちゃんと格納されるのか分かりません。 「ArrayListより、HashMapを取得する。」←特にこの部分を どう記述してよいのか・・・ 分かる方、上記の部分の記述方法だけでも構わないので教えて下さい。 『自分で書いたプログラム』 import java.util.*; import java.io.*; public class Sample02{ public static void main(String[] args)throws IOException{ ArrayList list = new ArrayList(); System.out.println("何回で入力しますか?"); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String str = br.readLine(); int num = Integer.parseInt(str); for(int i=0; i<num; i++){ HashMap map = new HashMap(); System.out.println("名前を入力して下さい。"); String name = br.readLine(); System.out.println("年齢を入力して下さい。"); String age = br.readLine(); System.out.println("性別を入力して下さい。"); String sex= br.readLine(); map.put("名前", name); map.put("年齢",age); map.put("性別",sex); list.add(name); list.add(age); list.add(sex); } for(int i=0; i<num; i++){ HashMap map = new HashMap(); String name = (String)map.get("名前"); String age = (String)map.get("年齢"); String sex = (String)map.get("性別"); System.out.println("名前=" + name); System.out.println("年齢=" + age); System.out.println("性別=" + sex); } } }

    • ベストアンサー
    • Java
  • メモリ領域確保に関して

    C言語を始めて3ヶ月の初心者です。 下記のような定義で、領域確保をしたいのですが、 うまい方法がわかりません。 ご存知の方いらっしゃいましたら、 御知恵をお貸し下さいませんでしょうか? <test.h> ================================== #define SIZE_A (5) /* 親構造体 */ typedef struct { int testInt; testSmallStructT *testSmall; // 7バイト構造体の配列 char *testChar; // SIZE_A分の領域*配列数 } testBigStructT; /* 7バイト構造体 */ typedef struct { char str1[3]; char str2[4]; } testSmallStructT; /* メンバ変数 */ testBigStructT gTest[10]; ================================== ここで、あらかじめ全体の領域サイズを算出して、 mallocにてエリア確保を行う方法を求めてます。 また、多数にmallocを使用するとメモリ確保失敗時に、 それまで確保したエリアの開放を行わなくてはいけなくなる懸念から、 できるだけ使用しないようにしたいのです。 メンバ変数gTestを10の配列で持ち、構造体testBigStructTの、 要素testSmallとtestCharを可変の配列として扱いたくポインタ定義をしており、 更に、testCharにSIZE_A(5byte)の領域を確保しようとしております。 最終的には、下記のような使い方をしたいのですが、 メモリ確保の方法がわかりません。 =================================== (EX:) strcpy(gTest[0].testSmall[0].str1,"aaa"); strcpy(gTest[3].testSmall[2].str2,"bbb"); strcpy(gTest[6].testChar[3],"cccc"); =================================== 開放は下記の記述で問題ないと思っております。 free(gTest); 大変申し訳御座いませんが、 ご指摘・ご指導願いませんでしょうか? どうか宜しくお願い致します。

  • HashMap.putについて

    ご質問させて頂きます。 hashMap.putの使い方が良く分かりません。 例えば、以下のようなkudamono.csvファイルがあるとします。 ------------------- A,2003/01/01,スイカ B,2003/02/01,バナナ C,2003/03/01,メロン D,2003/04/01,イチゴ ------------------- このデータをhashMap.putでセットしたいので 以下のようなクラスにしたんですが コンパイルエラーが出てしまいます。 ------------------- /*HashMap生成(クラス変数)*/ public static HashMap hashMap = new HashMap(); public static void main(String args[]) throws Exception { FileReader filereader = new FileReader("kudamono.csv"); BufferedReader bufferedreader = new BufferedReader(filereader); String line; int i = 1; int j = 0; while((line = bufferedreader.readLine()) != null) { System.out.println("Start line at " + i); StringTokenizer stringTokenizerTest = new StringTokenizer(line, ","); while(stringTokenizerTest.hasMoreTokens()) { HashMap.put(stringTokenizerTest.nextToken().toString()); j++; } i++; } filereader.close(); } } --------------- たぶんHashMap.putをする前に キーをセットしたり変数を宣言したりすると思うのですが その辺が良く分かりません。 ご教授して頂けたら幸いです。

    • ベストアンサー
    • Java
  • 関数内での多次元配列のメモリの動的確保について

    関数内で、参照渡しをして配列の動的なメモリの確保をしようとしているのですが、うまくいきません。 はじめに、main関数内で、 int main(void){ double *testdata1; testdata1 = (double*)malloc( sizeof(double) * 10 ); if( testdata1 == NULL ){ printf( "ERROR:testdata1" ); exit(0); } testdata1[3] = 20.4; printf( "test = %g\n", testdata1[3] ); } を実行したところうまくいきました。 そこで、 int main(void){ double *testdata1; Kakuho( &testdata1 ); printf( "test = %g\n", testdata1[3] ); } void Kakuho( double **testdata2 ){ *testdata2 = (double*)malloc( sizeof(double) * 10 ); if( *testdata2 == NULL ){ printf( "ERROR:testdata2" ); exit(0); } *testdata2[3] = 20.4; } としましたが、成功してくれません。 コンパイルは通りますが実行するとエラーが発生して落ちます。 (上記のprintfのERRORではありません。) 動作環境はXPのVCC7です。よろしくお願いします。

専門家に質問してみよう