- PR -

Hashtableへ格納するオブジェクトのガベージコレクト

1
投稿者投稿内容
schpeltor
会議室デビュー日: 2003/02/28
投稿数: 3
投稿日時: 2004-03-08 12:59
ガベージコレクトについて質問です。

staticなHashtableを持つ常駐オブジェクトが存在します。
また、2つのStringをメンバに持つオブジェクトが存在し、
get1(),get2()メソッドでそれぞれのString値が取得できるとします。

そこで、
XXX o1 = new XXX("1", "111");
XXX o2 = new XXX("1", "222");
とし、
hashtable.put(o1.get1(), o1);
と、o1の持つメンバをキーにし、o1自身を値にセットした後で、
hashtable.put(o2.get1(), o2);
と、キー"1"に対する値をo2に変更した場合、
o1はガベージコレクトの対象になるのでしょうか?

最初にo1のメンバをキーにセットしているので、
そのキーが削除されない限り、
o1への参照がなくならず、o1がガベージコレクトの
対象にならないのかな?と思ったのですが、
どなたかご教示いただけませんでしょうか?

また、Hashtableクラスのremove()メソッドでは
キーの削除は行われないのでしょうか?
実装を見ると、Entryのvalueはnullにされていますが
keyは何も操作されていないように見えたので・・・
t-wata
大ベテラン
会議室デビュー日: 2002/07/12
投稿数: 209
お住まい・勤務地: 東京
投稿日時: 2004-03-08 16:46
> o1はガベージコレクトの対象になるのでしょうか?

なります。

> o1への参照がなくならず

誰がo1を参照していると考えているのでしょうか?o1はキーの参照を
持っているけど、、、

> また、Hashtableクラスのremove()メソッドでは
> キーの削除は行われないのでしょうか?

行われます。

> 実装を見ると、Entryのvalueはnullにされていますが
> keyは何も操作されていないように見えたので・・・

エントリごと参照をはずしているから、わざわざ削除する
必要がないのです。
schpeltor
会議室デビュー日: 2003/02/28
投稿数: 3
投稿日時: 2004-03-08 18:24
t-wata様 ご回答ありがとうございます。

> 誰がo1を参照していると考えているのでしょうか?o1はキーの参照を
> 持っているけど、、、

hashtable.put(o2.get1(), o2); とした際に、
o1.get1()で参照しているオブジェクトと
o2.get1()で参照しているオブジェクトのハッシュコードが等しく、
o1.get1().equals(o2.get1())が真であるため、
Entryのvalueの置き換えが行われる。

そこで実際に行われるのは、
hashtable.put(o1.get1(), o1);
の際に新たに追加されたEntryのvalueの置き換えであり、
このEntryのkeyはo1.get1()の参照を保持しているため、
「valueはo2を参照するようになったものの、
 keyはo1への参照が外れていない」のではないか?と
思っているのですが、私の参照に対する理解が
誤っているのでしょうか???

見当はずれな理解でしたら、申し訳ありません・・・
ueshin
会議室デビュー日: 2003/01/30
投稿数: 10
お住まい・勤務地: 東京都
投稿日時: 2004-03-08 18:52
こんにちは、ueshinです。

僕もガーベジコレクト対象になると思います。

引用:

そこで実際に行われるのは、
hashtable.put(o1.get1(), o1);
の際に新たに追加されたEntryのvalueの置き換えであり、
このEntryのkeyはo1.get1()の参照を保持しているため、
「valueはo2を参照するようになったものの、
 keyはo1への参照が外れていない」のではないか?と
思っているのですが、私の参照に対する理解が
誤っているのでしょうか???



この場合のkeyは、「o1.get1()の参照」としての"1"ではなく、「o2.get1()の参照」としての"1"でもなく、ただの文字列(String型の)"1"です。例えば、
コード:
hashtable.put(o1.get1(), o1);


は、
コード:
 String aKey = o1.get1();
 hashtable.put(aKey, o1);


としているのと同じです。
なので、hashtable.put(o2.get1(), o2); としても、keyが"1"に対応する値を変更、という意味しかなく、o1への参照はこの時点で切れてしまいます。

結局、「要らないからポイ!」ということになると思います。
_________________
いじょ。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2004-03-08 21:07
unibon です。こんにちわ。
読んでも意味が良く分からなかったこともあり、完結したサンプルコードを書いて試してみました。
コード:
import java.util.*;

public class GCTester {

    private static class XXX {
        private final String field1;
        private final String field2;
        public XXX(String aField1, String aField2) {
            field1 = aField1;
            field2 = aField2;
        }
        public String get1() {
            return field1;
        }
        public String get2() {
            return field2;
        }
        protected void finalize() throws Throwable {
            System.out.println("finalize: " + this
            +", field1 = " + field1 + ", field2 = " + field2);
            super.finalize();
        }
    }

    private static void foo() {
        System.out.println("foo");
    }

    public static void main(String[] args) {
        XXX hoge = new XXX("hohoge", "hogege");
        XXX o1 = new XXX("1", "111");
        XXX o2 = new XXX("1", "222");
        Hashtable hashtable = new Hashtable();
        hashtable.put(o1.get1(), o1);
        hashtable.put(o2.get1(), o2);
        o1 = null;
        o2 = null;
        hoge = null;
        Runtime runtime = Runtime.getRuntime();
        runtime.gc();
        foo();
        runtime.gc();
        foo();
        runtime.gc();
    }
}



実行結果はつぎのようになりました(行の順序は多少異なる)。
コード:
foo
finalize: GCTester$XXX@f4a24a, field1 = 1, field2 = 111
finalize: GCTester$XXX@cac268, field1 = hohoge, field2 = hogege
foo


すなわち o1 が指していたインスタンスは解放されましたが、o2 は解放されませんでした。したがって o1 がガーベッジコレクションの対象になるか、という問いに対する解答は、「はい」です。
#逆(もし o1 が指していたインスタンスの finalize が動かなかったから o1 が指していたインスタンスは解放されない)は必ずしも言えませんが。
ueshin
会議室デビュー日: 2003/01/30
投稿数: 10
お住まい・勤務地: 東京都
投稿日時: 2004-03-08 22:34
こんにちは、ueshinです。

> unibon様
なるほど、そうやればGCの動作チェックができるのですね。
勉強になります。
#これって、実は常識!?
_________________
いじょ。
schpeltor
会議室デビュー日: 2003/02/28
投稿数: 3
投稿日時: 2004-03-09 10:07
なるほど。finalize()を実装することで、
ガベージコレクトの対象となったのかどうかが分かりますね。
参考にさせていただきます。

私の参照に対する理解が誤っていたようです。

t-wata様、ueshin様、unibon様
教示いただきありがとうございました。
1

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