2016-12-01 10 views
1

WeakHashMapにいくつかの値を入力してマップから削除するコードスニペットを次に示します。割り当てられたメモリはどのように扱われますか?ウィークハッシュマップは、参照解除されるとすぐにメモリを解放しますか?

import java.util.*; 
public class WeakHashMap_Main { 
    private static Map map; 

    public static void main(String args[]) { 
     map = new WeakHashMap(); 
     map.put(new String("ABC"), "XYZ"); 
     map.put(new String("DEF"), "PQR"); 

     map.remove("ABC"); 
     map.remove("DEF"); 
    } 
} 
+7

メモリの解放は、必要に応じてガーベッジコレクタによって行われます。特定の時間にメモリが解放される保証はありません。それはガベージコレクタの実装までです。通常、そのような強い保証は必要ありません。 GCがその仕事をして、それについて心配しないでください。 – Jesper

+0

これはgc関数が現在よく知られていると理解しています。私は週ハッシュマップの専門性について疑問を抱いていた。 –

答えて

1

のJavaドキュメント(jdk1.8.0_71)は、 は、通常使用されなくなった、キーのない場合WeakHashMap

エントリは自動的に削除されます、と言っています。より正確には、指定されたキーのマッピングが であることは、ガーベジコレクタによってキーが破棄されるのを妨げません。

これは明らかにkeyが破棄されたとき、そのEntry<K, V>Mapから削除されることを述べています。

ここで、keyが取り外されたときの状況を確認してください。以下に示すようremove(Object o)方法の コードスニペットは:

public V remove(Object key) { 
     Object k = maskNull(key); 
     int h = hash(k); 
     Entry<K,V>[] tab = getTable(); 
     int i = indexFor(h, tab.length); 
     Entry<K,V> prev = tab[i]; 
     Entry<K,V> e = prev; 

     while (e != null) { 
      Entry<K,V> next = e.next; 
      if (h == e.hash && eq(k, e.get())) { 
       modCount++; 
       size--; 
       if (prev == e) 
        tab[i] = next; 
       else 
        prev.next = next; 
       return e.value; 
      } 
      prev = e; 
      e = next; 
     } 

     return null; 
    } 

ことが観察できるように、この方法は、第一getTable()メソッドを呼び出すことにより、Entry<K, V>のアレイを取り込みます。 getTable()へのすべての呼び出しで、別の方法expungeStaleEntries()が呼び出されます。この特定の方法は、WeakEntriesをクリアして保持しているReferenceQueue<Object>で再生し、のから古いエントリを削除します。このメソッドのコードスニペットは、以下に見ることができる。

/** 
    * Expunges stale entries from the table. 
    */ 
    private void expungeStaleEntries() { 
     for (Object x; (x = queue.poll()) != null;) { 
      synchronized (queue) { 
       @SuppressWarnings("unchecked") 
        Entry<K,V> e = (Entry<K,V>) x; 
       int i = indexFor(e.hash, table.length); 

       Entry<K,V> prev = table[i]; 
       Entry<K,V> p = prev; 
       while (p != null) { 
        Entry<K,V> next = p.next; 
        if (p == e) { 
         if (prev == e) 
          table[i] = next; 
         else 
          prev.next = next; 
         // Must not null out e.next; 
         // stale entries may be in use by a HashIterator 
         e.value = null; // Help GC 
         size--; 
         break; 
        } 
        prev = p; 
        p = next; 
       } 
      } 
     } 
    } 

それがコードスニペットを介して見ることができるように、各エントリは、put(K, V)中にこのqueue(呼び出すコンストラクタでWeakHashMap、店舗そのエントリに追加される、こと

Entry<K,V> e = tab[i]; 
tab[i] = new Entry<>(k, value, queue, h, e); 

)と同じエントリがEXPUNGE動作中queueから取り出され、除去される。動作は、以下に示す通りです。この値が削除されたEntry<K, V>はnull e.value = nullに設定され、GC'dとなります。そして、はい、それはGCを制御しません。これは、WeakHashMapがキーでマップされた値を破棄するのを容易にする方法です。

+0

詳細な説明はありがとう..誰がexpungeStaleEntries()を呼び出しますか? WeakHashMap上の操作がこの関数を呼び出すようなのでしょうか? –

+1

あなたの学習のおかげで嬉しいです。 'expungeStaleEntries()'は 'WeakHashMap'内のプライベートメソッドです。前述の私の説明のように、privateエントリ [] getTable() 'メソッドによって呼び出されます。マップ上で 'remove(Object o)'メソッドが呼び出されると、 'remove()'メソッドはこの 'getTable()'を呼び出して、有効な配列 'Entries'を取得します。 –

0

メモリはオブジェクトが作成されるときに割り当てられます。任意の数の他のオブジェクトがそのオブジェクトへの参照を有し、したがってその割り当てられたメモリへの参照を有することができる。

ガベージコレクタは、どのオブジェクトがまだ参照されているか(弱参照されているもの)を判断するJVMの要素です。それは、もはや参照されていないすべてのメモリをヒープに戻し、再び使用する準備ができています。どんな状況下であれ、メモリが十分に少ない場合などは、ヒープに参照されているメモリだけを参照し、弱い参照ではその魔法を実行するので、プログラムはもはや有効ではないと判断できます。

WeakHashMap内のオブジェクトへの参照を入れてからそれらを取り出し、それらのオブジェクトへの唯一の参照であった場合、そのオブジェクトは参照されなくなり、ガベージコレクションに使用できます。

0

クラスWeakHasMapは、keysWeakReferencesで動作します。通常HashMapは、キーのStrongReferencesと連動します。

ガベージコレクションは、JVMによって自己規制されています。私たちは、System.gc()を呼び出すことによって、ガベージコレクションを実行するためにJVMに影響を与えることのみを試みることができます。 HashMapは、キーのガベージコレクションを防止します。 WeakHashMapは、キーがガベージコレクションされることを防ぎません。 HashMapに格納されているキーにはStrongReferenceが残っていない場合、明示的に削除されるまでHashMapに保存されたままになります。その後、キーオブジェクトはガベージコレクションの対象となります。しかし、StrongReferenceのないキーがWeakHashMapに格納されている場合は、ガベージコレクションの対象となります。ガベージコレクションのサイクルが実行されるとすぐにガベージコレクションが行われ、そのキーオブジェクトのメソッドがfalseを返します。

1

WeakHashMapが使用するメモリが以下のようなシナリオで解放されることがあります。

public static void main(String args[]) { 
    Map<String, String> map = new WeakHashMap<>(); 
    String abc = "ABC"; 
    String def = "DEF"; 
    map.put(abc, "XYZ"); 
    map.put(def, "PQR"); 
    System.out.println(map.size()); // Guaranteed to be 2. 

    // Note: DO NOT remove the map entries! 
    // map.remove("ABC"); 
    // map.remove("DEF"); 

    // Allow the objects to be reclaimed 
    abc = null; 
    def = null; 

    // Do loads of memory-hungry operations here... 
    ... 

    System.out.println(map.size()); // MAY POSSIBLY be 0 or 1. Or still 2. 
} 

これは、すべてのガベージコレクタは、(すべてではどちらかといえば)を行うことを決定したかに依存します。

ここでのポイントは、2つのエントリを追加した後で地図に触れていないことです。

+0

マップエントリを削除しない理由はありますか?私はキーをnullにすることはできますが、WaelHashMapからkay値を取り除くのと同じ効果があると私は理解しています。右? –

+1

必要に応じてマップエントリを削除できますが、それを行う場合は、通常のHashMapを使用することもできます。私のコード例はWeakHashMapとHashMapの違いを示しています。 –

+0

多くのありがとう.. :) –

関連する問題