- PR -

ガベージコレクションの対象となるタイミングについて

投稿者投稿内容
Wata
ぬし
会議室デビュー日: 2003/05/17
投稿数: 279
投稿日時: 2003-11-19 11:53
引用:

begoodさんの書き込み (2003-11-19 11:25) より:
何か勘違いしている部分があったら教えていただきたく。


String a = new String("ABC");

String a = "ABC";
に変えたのは勘違いですか?
あとコードを掲載するときはコードタグを使った方が見やすくなりますよ。

# 訂正
もとからString a = "ABC";でしたね。上記は無視してください。
あれ?どこで勘違いしたんだ?

# 更に追記
String a = "ABC";の場合だと、"ABC"は解放されないようです。
(l4とl3の差分は16しかありませんでした。bが解放された分のみです。)
おそらく、コンスタントプールに入っているからでしょう。

それと、オブジェクトが解放されたかどうかをfreeMemoryの値で知るのも少々無理があるように思います。
GCやfinalizeのスレッドが他でメモリを使っているかもしれないですからね。

[ メッセージ編集済み 編集者: Wata 編集日時 2003-11-19 12:38 ]

[ メッセージ編集済み 編集者: Wata 編集日時 2003-11-19 12:51 ]
Wata
ぬし
会議室デビュー日: 2003/05/17
投稿数: 279
投稿日時: 2003-11-19 13:00
Stringだとfinalizeがオーバーライドできないと言う事なので、弱参照を使ってみました。
コード:
import java.lang.ref.WeakReference;
public class Test {
   public static void main(String[] args) {
      
      String[] b = new String[1];
      String a = "ABC";
//    String a = new String("ABC");
      b[0] = a;
      
      WeakReference ref = new WeakReference(a);
      System.out.println(ref.get());
      
      System.gc();

      a = null;
      System.gc();
      System.out.println(ref.get());

      b[0] = null;
      System.gc();
      System.out.println(ref.get());
      
      b = null;
      System.gc();
      System.out.println(ref.get());

      System.out.println("Bye");
   }
}


a = "ABC"の場合は最後まで参照可能でした。
a = new String("ABC")の場合は、b[0]=nullの後でオブジェクトは破棄されています。
アティ
ベテラン
会議室デビュー日: 2003/08/14
投稿数: 91
お住まい・勤務地: KANAGAWA
投稿日時: 2003-11-19 13:03
"ABC"とnew String("ABC")の違いは初めて知りました。
それで、begoodさんのプログラムだと、もともとの問題でb=nullの後で空きメモリが増えたのは、
String配列型のインスタンスがガーベッジコレクションの対象にされたためとしか分からないですね。

ということで、正解は、
E:ガーベッジコレクションの対象にならない。(というか、問題製作者が悪い)
ってことでどうでしょ?
begood
ベテラン
会議室デビュー日: 2003/09/12
投稿数: 97
お住まい・勤務地: とうきょー
投稿日時: 2003-11-19 16:04
Object型での実験は、まさに、アドレスを見てみないと分からないものに結論ずく形になりました。finalizeを呼べば、freeMemoryの値が変わってしまうのではと思い、Objectではためさなかったためで、実験したところ、gc()はメモリスペースを使用していないようです。ただ、本来ガーベッジコレクトがされるときにメモリが使用されてしまうのでは・・・、ということでどうにかして、アドレスを知りたく。gcをたくさんいれても、ガーベッジコレクトはいくつかの部分では正常にされていないのかもしれません。ただ、結論はメモリのアドレスを完全にみきるまではなんともいえない部分です。完全に調べるメソッドが隠されてしまっているのかと途方にくれています・・・。

アティさんの言われているように確かに出題に、混乱を招く部分がありますね。だから、逆にはっきりさせたいなんて、思っています。(すいません・・・うやむやはいやなもので・・・エンジニアには向かないかもしれないですね・・・。)

なお、文字リテラルが開放されることがないというのは、JVMを終了させるまで開放されることはないということですか?まさか・・・と思うのですが。
win-win
常連さん
会議室デビュー日: 2003/03/23
投稿数: 49
投稿日時: 2003-11-19 16:29
引用:

たーぞうさんの書き込み (2003-11-17 20:57) より:
僕もよくわからないんですけど、もしかして

b[0] = a;

とやった時に、"ABC"というオブジェクトが新たに生成されて、b[0]には新しいオブジェクトへの参照が格納される・・・なんてことが起きていたとすれば現象面の説明はできますね。

ただし責任は持てません^^;



以下のコードの追加行の出力が「true」になったとしたら、
上記の仮説は信憑性が薄れると思います。

コード:
public class Sample {
	public static void main(String args[]){
		String[] b = new String[1];
		String a = "ABC";
		b[0] = a;
		System.out.println(b[0] == a); // 追加行
		a = null;
		b[0] = null;
		b = null;
		System.out.println("Bye");		
	}
}



ちなみに、私のところでは「true」でした。

# 責任をお持ちならなくて良かったと思います。^^;
Wata
ぬし
会議室デビュー日: 2003/05/17
投稿数: 279
投稿日時: 2003-11-19 17:43
引用:

アティさんの書き込み (2003-11-19 13:03) より:
"ABC"とnew String("ABC")の違いは初めて知りました。


違いとしては、newを行うと常にヒープ領域に新しいインスタンスが作成されるので、
("ABC" == new String("ABC"))の値は常にfalseになります。
ちなみに、("ABC" == new String("ABC").intern())の値は常にtrueになります。
しかし、実際のところ、new String("ABC")のコンストラクタは使い道がありません。
引用:

正解は、
E:ガーベッジコレクションの対象にならない。(というか、問題製作者が悪い)
ってことでどうでしょ?


そうですね。リテラル文字列に対するVMの取扱いは試験の対象外だと思うので「問題製作者が悪い」でしょうね。

引用:

begoodさんの書き込み (2003-11-19 16:04) より:
Object型での実験は、まさに、アドレスを見てみないと分からないものに結論ずく形になりました。


begoodさんは「"ABC"がガベージコレクションの対象になるタイミング」ではなく、
「"ABC"のインスタンスが占有しているメモリ領域が解放されるタイミング」を知りたいのですか?
これこそGCの実装依存であり、無理して調べる価値も無いものだと思います。
# ちなみに、「"ABC"がガベージコレクションの対象になる条件」はGCの実装に依存しないと思います。
# ただ、実装によっては対象であるオブジェクトが見過ごされることはあるかもしれませんが。

引用:

なお、文字リテラルが開放されることがないというのは、JVMを終了させるまで開放されることはないということですか?


クラスがアンロードされるまでだと思います。
begood
ベテラン
会議室デビュー日: 2003/09/12
投稿数: 97
お住まい・勤務地: とうきょー
投稿日時: 2003-11-19 19:35
ごくごく単純に、PCのシステムメモリに展開している形になると思いますが、CPUのキャッシュでもなんでもいいのですが、そのメモリ内部の番地を知りたいのです・・・。やはり、Cを混ぜないとだめですかねぇ。

未記入
ぬし
会議室デビュー日: 2002/03/28
投稿数: 255
投稿日時: 2003-11-19 21:20
>ごくごく単純に、PCのシステムメモリに展開している形になると思いますが、
>CPUのキャッシュでもなんでもいいのですが、そのメモリ内部の番地を知りたいのです・・・。
あのー.

インスタンスのアドレス(置かれている領域)は変化することもあるってこと,
分かってます?定数じゃないんですよ.

>やはり、Cを混ぜないとだめですかねぇ。
いや,たとえ過去のある瞬間のアドレスが取得できても,現在有効であるという
保証がないので無意味でしょう.

そういうのを取得するには,JVMの中にそのためのコードを挟み込まないとまず無理
だと思います.

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