public
static
void WeakReferenceTest(){
/**
*
弱引用的對象只能生存到下一次GC以前!
*/
String str
=
new String(
"avd");
WeakReference
<String
> wr
=
new WeakReference
<String
>(str);
str
= null;
//消除強引用
System.out.println(
"垃圾回收以前:"
+wr.get());
System.gc();
//垃圾回收
System.out.println(
"垃圾回收以後:"
+wr.get());
}
垃圾回收以前:avd
垃圾回收以後:null
public
class WeakHashMap
<K,V
>
extends AbstractMap
<K,V
>
implements Map
<K,V
>
/**
* The default initial capacity -- MUST be a power of two.
*/
// 默認加載因子16,必須爲2的冪
private
static
final
int DEFAULT_INITIAL_CAPACITY
=
16;
/**
* The maximum capacity, used if a higher value is implicitly specified
* by either of the constructors with arguments.
* MUST be a power of two <= 1<<30.
*/
// Entry[]最大長度
private
static
final
int MAXIMUM_CAPACITY
=
1
<<
30;
/**
* The load fast used when none specified in constructor.
*/
//默認加載因子
private
static
final
float DEFAULT_LOAD_FACTOR
=
0.
75f;
/**
* The table, resized as necessary. Length MUST Always be a power of two.
*/
private Entry[] table;
/**
* The number of key-value mappings contained in this weak hash map.
*/
// map中包含映射關係的數量
private
int size;
/**
* The next size value at which to resize (capacity * load factor).
*/
// 當size的值不小於threshold時,需擴展table,並從新計算映射關係的存儲位置,默認16*0.75=12
private
int threshold;
/**
* The load factor for the hash table.
*/
//實際加載因子
private
final
float
loadFactor;
/**
* Reference queue for cleared WeakEntries
*/
//引用隊列,每個弱引用entry須關聯此隊列,每次GC的弱引用entry會被添加到該隊列
private
final ReferenceQueue
<K
> queue
=
new ReferenceQueue
<K
>();
/**
* The number of times this WeakHashMap has been structurally modified.
* Structural modifications are those that change the number of
* mappings in the map or otherwise modify its internal structure
* (e.g., rehash). This field is used to make iterators on
* Collection-views of the map
fail-fast
.
*
* @see ConcurrentModificationException
*/
private
volatile
int modCount;
public Object get(Object arg
-
0);
public Object put(Object arg
-
0,Object arg
-
1);
public Collection values();
public
void clear();
public
boolean isEmpty();
public Set entrySet();
public
void putAll(Map arg
-
0);
public
int size();
public Object remove(Object arg
-
0);
public Set keySet();
public
boolean containsKey(Object arg
-
0);
public
boolean containsValue(Object arg
-
0);
public
boolean equals(Object arg
-
0);
public String toString();
public
int hashCode();
/**
* Value representing null keys inside tables.
*/
//
key爲null時,用NULL_KEY取代
private
static
final Object NULL_KEY
=
new Object();
/**
* Associates the specified value with the specified key in this map.
* If the map previously contained a mapping for this key, the old
* value is replaced.
*/
public V put(K key, V value) {
K k
= (K) maskNull(key);
//若是key == null,則key用NULL_KEY代替
int h
= HashMap.hash(k.hashCode());
Entry[] tab
= getTable();
//清理map中無效的引用
int i
= indexFor(h, tab.length);
for (Entry
<K,V
> e
= tab[i]; e
!= null; e
= e.next) {
if (h
== e.hash
&& eq(k, e.get())) {
V oldValue
= e.value;
if (value
!= oldValue)
e.value
= value;
return oldValue;
}
}
modCount
++;
Entry
<K,V
> e
= tab[i];
tab[i]
=
new Entry
<K,V
>(k, value, queue, h, e);
//將新的元素添加到哈希表
if (
++size
>
= threshold)
resize(tab.length
*
2);
//擴展Entry[]到原來的2倍
return null;
}
/**
* Use NULL_KEY for key if it is null.
*/
private
static Object maskNull(Object key) {
return (key
== null
? NULL_KEY
: key);
}
/**
* Applies a supplemental hash function to a given hashCode, which
* defends against poor quality hash functions. This is critical
* because HashMap uses power-of-two length hash tables, that
* otherwise encounter collisions for hashCodes that do not differ
* in lower bits. Note: Null keys always map to hash 0, thus index 0.
*/
// hash 函數
static
int hash(
int h) {
// This function ensures that hashCodes that differ only by
// constant multiples at each bit position have a bounded
// number of collisions (approximately 8 at default load factor).
h
^= (h
>>>
20)
^ (h
>>>
12);
return h
^ (h
>>>
7)
^ (h
>>>
4);
}
/**
* Returns index for hash code h.
*/
// 從新計算entry的桶的位置
static
int indexFor(
int h,
int length) {
return h
& (length
-
1);
}
/**
* Rehashes the contents of this map into a new array with a
* larger capacity. This method is called automatically when the
* number of keys in this map reaches its threshold.
*
* If current capacity is MAXIMUM_CAPACITY, this method does not
* resize the map, but sets threshold to Integer.MAX_VALUE.
* This has the effect of preventing future calls.
*/
//擴展Entry[]的容量
void resize(
int newCapacity) {
Entry[] oldTable
= getTable();
int oldCapacity
= oldTable.length;
if (oldCapacity
== MAXIMUM_CAPACITY) {
threshold
= Integer.MAX_VALUE;
return;
}
Entry[] newTable
=
new Entry[newCapacity];
transfer(oldTable, newTable);
table
= newTable;
/*
* If ignoring null elements and processing ref queue caused massive
* shrinkage, then restore old table. This should be rare, but avoids
* unbounded expansion of garbage-filled tables.
*/
//擴展容量以後,剩餘元素不多,則收縮哈希表的容量到上一次未擴容是的大小,減小內存佔用。
if (size
>
= threshold
/
2) {
threshold
= (
int)(newCapacity
* loadFactor);
}
else {
expungeStaleEntries();
transfer(newTable, oldTable);
table
= oldTable;
}
}
/** Transfers all entries from src to dest tables */
//將舊哈希表中的映射關係添加到新哈希表中
private
void transfer(Entry[] src, Entry[] dest) {
for (
int j
=
0; j
< src.length;
++j) {
Entry
<K,V
> e
= src[j];
src[j]
= null;
while (e
!= null) {
Entry
<K,V
> next
= e.next;
// e的下一個entry
Object key
= e.get();
// T get():返回註冊的引用對象,若是此對象已回收,將返回null
if (key
== null) {
// key == null, 解除對下一個entry 和value的引用
e.next
= null;
// Help GC
e.value
= null;
// " "
size
--;
//不放到新哈希表中,因此其size應-1
}
else {
int i
= indexFor(e.hash, dest.length);
e.next
= dest[i];
dest[i]
= e;
}
e
= next;
//e指向下一個entry
}
}
}
/**
* Returns the table after first expunging stale entries.
*/
//清除過期無效的引用
private Entry[] getTable() {
expungeStaleEntries();
return table;
}
/**
* Expunges stale entries from the table.
*/
private
void expungeStaleEntries() {
Entry
<K,V
> e;
while ( (e
= (Entry
<K,V
>) queue.poll())
!= null) {
//輪詢此隊列 ,再遍歷對應的桶
int h
= e.hash;
int i
= indexFor(h, 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) {
//p == e 說明該對象存在於隊列之中,說明已經被垃圾回收器回收。
if (prev
== e)
//prev == e說明桶的第一個元素被回收
table[i]
= next;
//table[i]存放其下一個元素,prev和p指向next
else
prev.next
= next;
//prev越過p指向p.next
//解除引用,結束循環
e.next
= null;
// Help GC
e.value
= null;
// " "
size
--;
break;
}
//說明元素p未被回收
prev
= p;
p
= next;
//使p指向下一個元素
}
}
}
第一個元素被回收的狀況:
初始狀態:
第一次循環:移除table[i]位置的元素,下一個元素置於table[i]位置,該桶的循環結束
第一個元素不被回收的狀況:
第一次循環:
第二次循環移除第二個元素:這個桶的循環結束
/**
* The entries in this hash table extend WeakReference, using its main ref
* field as the key.
*/
//哈希表中存儲 的弱引用對象,
最終繼承自 Reference 抽象類。
private
static
class Entry
<K,V
>
extends WeakReference
<K
>
implements Map.Entry
<K,V
> {
private V value;
private
final
int hash;
private Entry
<K,V
> next;
/**
* Creates new entry.
*/
Entry(K key, V value,
ReferenceQueue
<K
> queue,
int hash, Entry
<K,V
> next) {
super(key, queue);
this.value
= value;
this.hash
= hash;
this.next
= next;
}
public K getKey() {
return WeakHashMap.
<K
>unmaskNull(get());
//獲取當前映射關係的key.
}
public V getValue() {
return value;
}
public V setValue(V newValue) {
V oldValue
= value;
value
= newValue;
return oldValue;
}
public
boolean equals(Object o) {
if (
!(o
instanceof Map.Entry))
return false;
Map.Entry e
= (Map.Entry)o;
Object k1
= getKey();
Object k2
= e.getKey();
if (k1
== k2
|| (k1
!= null
&& k1.equals(k2))) {
Object v1
= getValue();
Object v2
= e.getValue();
if (v1
== v2
|| (v1
!= null
&& v1.equals(v2)))
return true;
}
return false;
}
public
int hashCode() {
Object k
= getKey();
Object v
= getValue();
return ((k
==null
?
0
: k.hashCode())
^
(v
==null
?
0
: v.hashCode()));
}
public String toString() {
return getKey()
+
"="
+ getValue();
}
}
/**
* Returns internal representation of null key back to caller as null.
*/
//返回映射關係的key,若key爲NULL_KEY,則轉換爲null.
private
static
<K
> K unmaskNull(Object key) {
return (K) (key
== NULL_KEY
? null
: key);
}
/**
* Reference queue for cleared WeakEntries
*/
private final ReferenceQueue<K> queue = new ReferenceQueue<K>();
public V put(K key, V value) {
K k
= (K) maskNull(key);
int h
= HashMap.hash(k.hashCode());
Entry[] tab
= getTable();
int i
= indexFor(h, tab.length);
for (Entry
<K,V
> e
= tab[i]; e
!= null; e
= e.next) {
if (h
== e.hash
&& eq(k, e.get())) {
V oldValue
= e.value;
if (value
!= oldValue)
e.value
= value;
return oldValue;
}
}
modCount
++;
Entry
<K,V
> e
= tab[i];
tab[i]
=
new Entry
<K,V
>(k, value,
queue, h, e);
if (
++size
>
= threshold)
resize(tab.length
*
2);
return null;
}
private
static
class Entry
<K,V
>
extends
WeakReference
<K
>
implements Map.Entry
<K,V
> {
private V value;
private
final
int hash;
private Entry
<K,V
> next;
/**
* Creates new entry.
*/
Entry(K key, V value,
ReferenceQueue
<K
> queue,
int hash, Entry
<K,V
> next) {
super(key, queue);
this.value
= value;
this.hash
= hash;
this.next
= next;
}
public K getKey() {
return WeakHashMap.
<K
>unmaskNull(get());
}
public V getValue() {
return value;
}
public V setValue(V newValue) {
V oldValue
= value;
value
= newValue;
return oldValue;
}
public
boolean equals(Object o) {
if (
!(o
instanceof Map.Entry))
return false;
Map.Entry e
= (Map.Entry)o;
Object k1
= getKey();
Object k2
= e.getKey();
if (k1
== k2
|| (k1
!= null
&& k1.equals(k2))) {
Object v1
= getValue();
Object v2
= e.getValue();
if (v1
== v2
|| (v1
!= null
&& v1.equals(v2)))
return true;
}
return false;
}
public
int hashCode() {
Object k
= getKey();
Object v
= getValue();
return ((k
==null
?
0
: k.hashCode())
^
(v
==null
?
0
: v.hashCode()));
}
public String toString() {
return getKey()
+
"="
+ getValue();
}
}
/**
* Creates a new weak reference that refers to the given object and is
* registered with the given queue.
*/
public
WeakReference(T referent, ReferenceQueue
<
?
super T
> q) {
super(referent, q);
}
private T referent;
/* Treated specially by GC */
ReferenceQueue
<
?
super T
> queue;
Reference(T referent, ReferenceQueue
<
?
super T
> queue) {
this.referent
= referent;
this.queue
= (queue
== null)
? ReferenceQueue.NULL
: queue;
}
當垃圾回收時:
回收弱引用中的key
Reference的內部類線程被調用,將被回收的弱引用對象添加到隊列
private
static
class
ReferenceHandler
extends
Thread {
ReferenceHandler(ThreadGroup g, String name) {
super(g, name);
}
public
void run() {
for (;;) {
Reference r;
synchronized (lock) {
if (pending
!= null) {
r
= pending;
Reference rn
= r.next;
pending
= (rn
== r)
? null
: rn;
r.next
= r;
}
else {
try {
lock.wait();
}
catch (InterruptedException x) { }
continue;
}
}
// Fast path for cleaners
if (r
instanceof Cleaner) {
((Cleaner)r).clean();
continue;
}
ReferenceQueue q
= r.queue;
if (q
!= ReferenceQueue.NULL)
q.enqueue(r);
}
}
}
private
volatile Reference
<
?
extends T
> head
= null;
private
long queueLength
=
0;
boolean
enqueue(Reference
<
?
extends T
> r) {
/* Called only by Reference class */
synchronized (r) {
if (r.queue
== ENQUEUED)
return false;
synchronized (lock) {
r.queue
= ENQUEUED;
r.next = (head == null) ? r : head;
head = r;
queueLength
++;
if (r
instanceof FinalReference) {
sun.misc.VM.addFinalRefCount(
1);
}
lock.notifyAll();
return true;
}
}
}
public String toString() {
Iterator<Entry<K,V>> i = entrySet().iterator();
if (
! i.hasNext())
return
"{}";
StringBuilder sb
=
new StringBuilder();
sb.append(
'{');
for (;;) {
Entry
<K,V
> e
= i.next();
K key
= e.getKey();
V value
= e.getValue();
sb.append(key
==
this
?
"(this Map)"
: key);
sb.append(
'=');
sb.append(value
==
this
?
"(this Map)"
: value);
if (
! i.hasNext())
return sb.append(
'}').toString();
sb.append(
", ");
}
}
private
abstract
class HashIterator
<T
>
implements Iterator
<T
> {
int index;
HashIterator() {
index
= (
size()
!=
0
? table.length
:
0);
}
}
/**
* Returns the number of key-value mappings in this map.
* This result is a snapshot, and may not reflect unprocessed
* entries that will be removed before next attempted access
* because they are no longer referenced.
*/
public
int size() {
if (size
==
0)
return
0;
expungeStaleEntries();
return size;
}