引用这个概念经常被提及,今天总结一下。
强引用
强引用即(StrongReference)我们最常使用的引用,A a=new A()。这个a就是一个强引用。
软引用
即(SoftReference),
Object obj = new Object();
SoftReference<Object> sf = new SoftReference<Object>(obj);
obj = null;
sf.get();//有时候会返回null
弱引用
即(WeakReference)
Object obj = new Object();
WeakReference<Object> wf = new WeakReference<Object>(obj);
obj = null;
wf.get();//有时候会返回null
wf.isEnQueued();//返回是否被垃圾回收器标记为即将回收的垃圾
虚引用
即(PhantomReference)
Object obj = new Object();
PhantomReference<Object> pf = new PhantomReference<Object>(obj);
obj=null;
pf.get();//永远返回null
pf.isEnQueued();//返回是否从内存中已经删除
引用的作用
强引用就不说了,大家都知道。软引用一般可以用来做缓存,比如一个很大的对象,我们重新加载比较耗时间,用强引用又可能内存溢出,就用软引用咯。
弱引用的典型引用就是WeakHashMap,有时候我们想要JVM快速回收某个对象时,就用弱引用。
下面来个例子:
package weakmap;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
public class ThreadGC implements Runnable {
private WeakReference<byte[]> k;
private ReferenceQueue referenceQueue;
public void setReferenceQueue(ReferenceQueue referenceQueue) {
this.referenceQueue=referenceQueue;
}
@Override
public void run() {
// TODO Auto-generated method stub
int cnt = 0;
try {
while((k = (WeakReference) referenceQueue.remove()) != null) {
System.out.println((cnt++) + "回收了:" + k);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package weakmap;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
Object value = new Object();
Map<Object, Object> map = new HashMap<>();
ReferenceQueue referenceQueue=new ReferenceQueue<>();
ThreadGC threadGC=new ThreadGC();
threadGC.setReferenceQueue(referenceQueue);
new Thread(threadGC).start();
for(int i = 0;i < 10000;i++) {
byte[] bytes = new byte[1024*1024];
WeakReference<byte[]> weakReference = new WeakReference<byte[]>(bytes, referenceQueue);
map.put(weakReference, value);
}
System.out.println("map.size->" + map.size());
}
}
WeakHashMap应该也是类似的实现,把HashMap的key用弱引用,可以实现快速内存回收。
虚引用:
下面来个例子:
package weakmap;
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.reflect.Field;
public class Test {
public static boolean isRun = true;
@SuppressWarnings("static-access")
public static void main(String[] args) throws Exception {
String abc = new String("abc");
System.out.println(abc.getClass() + "@" + abc.hashCode());
final ReferenceQueue<String> referenceQueue = new ReferenceQueue<String>();
new Thread() {
public void run() {
while (isRun) {
Object obj = referenceQueue.poll(); //引用队列里有对象
if (obj != null) {
try {
Field rereferent = Reference.class
.getDeclaredField("referent");
rereferent.setAccessible(true);
Object result = rereferent.get(obj);
System.out.println("gc will collect:"
+ result.getClass() + "@"
+ result.hashCode() + "\t"
+ (String) result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}.start();
PhantomReference<String> abcWeakRef = new PhantomReference<String>(abc,
referenceQueue);
abc = null;
Thread.currentThread().sleep(3000);
System.gc();
Thread.currentThread().sleep(3000);
isRun = false;
}
}