启动的时候要加上启动配置: -Xms10m -Xmx10m -verbose:gc
如果要使用Jconsole还要加上 :-Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
所有代码用这个类作为测试
public class ReferenceCountingGC {
public final int _1M = 1024*1024;
public ReferenceCountingGC ref = null;
private byte[] content;
public ReferenceCountingGC(int num) {
this.content = new byte[_1M*num];
}
public ReferenceCountingGC() {
this.content = new byte[_1M*1];
}
}
1、 强引用
只要引用存在,垃圾回收器永远不会回收
Object obj = new Object();
//可直接通过obj取得对应的对象 如obj.equels(new Object());
而这样 obj对象对后面new Object的一个强引用,只有当obj这个引用被释放之后,对象才会被释放掉,这也是我们经常所用到的编码形式。
2、 软引用
非必须引用,内存溢出之前进行回收,可以通过以下代码实现
sf.get();//有时候会返回null
这时候sf是对obj的一个软引用,通过sf.get()方法可以取到这个对象,当然,当这个对象被标记为需要回收的对象时,则返回null;
软引用主要用户实现类似缓存的功能,在内存足够的情况下直接通过软引用取值,无需从繁忙的真实来源查询数据,提升速度;当内存不足时,自动删除这部分缓存数据,从真正的来源查询这些数据。
public class TestSoftReference {
public static void main(String[] args) throws InterruptedException {
ReferenceCountingGC a = new ReferenceCountingGC();
ReferenceQueue<Object> queue = new ReferenceQueue<>();
SoftReference<Object> sf = new SoftReference<Object>(a,queue);
a = null;
while (true) {
Thread.sleep(2000);
//不溢出
//ReferenceCountingGC b = new ReferenceCountingGC(3);
//溢出
ReferenceCountingGC b = new ReferenceCountingGC(6);
if (sf.get() != null) {
System.out.println("softReference Queued: " + sf.isEnqueued()+" => softReference : exists");
} else {
System.out.println("softReference Queued: " + sf.isEnqueued()+" => softReference : null");
}
}
}
}
3、 弱引用
垃圾回收时回收,
wf.get();//有时候会返回null
wf.isEnQueued();//返回是否被垃圾回收器标记为即将回收的垃圾
只要JVM进行垃圾回收,被弱引用关联的对象必定会被回收掉。
不过要注意的是,这里所说的被弱引用关联的对象是指只有弱引用与之关联,如果存在强引用同时与之关联,则进行垃圾回收时也不会回收该对象(软引用也是如此)。弱引用主要用于监控对象是否已经被垃圾回收器标记为即将回收的垃圾,可以通过弱引用的isEnQueued方法返回对象是否被垃圾回收器
public class TestWeakReference {
public static void main(String[] args) throws InterruptedException {
ReferenceCountingGC b = new ReferenceCountingGC();
ReferenceQueue<Object> wfQueue = new ReferenceQueue<>();
WeakReference<ReferenceCountingGC> wf = new WeakReference<>(b,wfQueue);
//释放强引用
b = null;
while (true) {
Thread.sleep(2000);
if (wf.get() != null) {
System.out.println("Weak Queued: " + wf.isEnqueued()+" => weakRefence : exists");
} else {
System.out.println("Weak Queued: " + wf.isEnqueued()+" => weakRefence : null");
}
ReferenceCountingGC c = new ReferenceCountingGC(2);
}
}
}
4、 虚引用(幽灵/幻影引用)
垃圾回收时回收,无法通过引用取到对象值
pf.get();//永远返回null
pf.isEnQueued();//返回从内存中已经删除
虚引用是每次垃圾回收的时候都会被回收,通过虚引用的get方法永远获取到的数据为null,因此也被成为幽灵引用。
虚引用主要用于检测对象是否已经从内存中删除。
public class TestPhantomReference {
public static void main(String[] args) throws InterruptedException {
ReferenceCountingGC b = new ReferenceCountingGC();
ReferenceQueue<Object> queue = new ReferenceQueue<>();
PhantomReference<Object> pf = new PhantomReference<Object>(b, queue);
//释放强引用
b = null;
while (true) {
Thread.sleep(2000);
ReferenceCountingGC c = new ReferenceCountingGC(2);
if (pf.get() != null) {
System.out.println("phantomReference Queued: " + pf.isEnqueued()+" => phantomReference : exists");
} else {
System.out.println("phantomReference Queued: " + pf.isEnqueued()+" => phantomReference : null");
}
}
}
}