public SoftReference(T referent) public SoftReference(T referent, ReferenceQueue super T> q)
WeakReference(弱引用)
public WeakReference(T referent) public WeakReference(T referent, ReferenceQueue super T> q)
PhantomReference(虚引用)
public PhantomReference(T referent, ReferenceQueue super T> q)
虚引用触发OOM
public static void main(String[] args) {
ReferenceQueue queue = new ReferenceQueue();
while (true) {
PhantomReference bytes = new PhantomReference(new byte[1024 * 1024 * 10], queue);
System.gc();
System.runFinalization();
// queue.poll(); // 不调用queue.poll()方法会触发OOM
}
}
api文档的说明
Phantom reference objects, which are enqueued after the collector determines that their referents may otherwise be reclaimed. Phantom references are most often used for scheduling pre-mortem cleanup actions in a more flexible way than is possible with the Java finalization mechanism.
If the garbage collector determines at a certain point in time that the referent of a phantom reference is phantom reachable, then at that time or at some later time it will enqueue the reference.
In order to ensure that a reclaimable object remains so, the referent of a phantom reference may not be retrieved: The get method of a phantom reference always returns null.
Unlike soft and weak references, phantom references are not automatically cleared by the garbage collector as they are enqueued. An object that is reachable via phantom references will remain so until all such references are cleared or themselves become unreachable.
使用场景
SoftHashMap
SoftHashMap实现了继承AbstractMap类, 实现对数据的缓存
org.aspectjaspectjweaver${version}
package org.aspectj.util;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.AbstractMap;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class SoftHashMap extends AbstractMap {
private Map map;
private ReferenceQueue super V> rq = new ReferenceQueue();
public SoftHashMap() {
this.map = new HashMap();
}
class SpecialValue extends SoftReference {
private final K key;
SpecialValue(K k, V v) {
super(v, rq);
this.key = k;
}
}
private void processQueue() {
SpecialValue sv = null;
while ((sv = (SpecialValue) rq.poll()) != null) {
map.remove(sv.key);
}
}
@Override
public V get(Object key) {
SpecialValue ref = map.get(key);
if (ref == null) {
map.remove(key);
return null;
}
V value = ref.get();
if (value == null) {
map.remove(ref.key);
return null;
}
return value;
}
@Override
public V put(K k, V v) {
processQueue();
SpecialValue sv = new SpecialValue(k, v);
SpecialValue result = map.put(k, sv);
return (result == null ? null : result.get());
}
@Override
public java.util.Set> entrySet() {
if (map.isEmpty()) {
return Collections.emptyMap().entrySet();
}
Map currentContents = new HashMap();
for (Map.Entry entry : map.entrySet()) {
V currentValueForEntry = entry.getValue().get();
if (currentValueForEntry != null) {
currentContents.put(entry.getKey(), currentValueForEntry);
}
}
return currentContents.entrySet();
}
@Override
public void clear() {
processQueue();
map.clear();
}
@Override
public int size() {
processQueue();
return map.size();
}
@Override
public V remove(Object k) {
processQueue();
SpecialValue ref = map.remove(k);
if (ref == null) {
return null;
}
return ref.get();
}
}
Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list.
For example,Given 1->2->3->3->4->4->5,