学而不思则罔,思而不学则殆
Java有四种引用, 强软弱虚
总结
引用类型 | type | 说明 |
---|---|---|
强引用 | StrongReference | 最普遍的引用 |
软引用 | SoftReference | 只有在内存不足的时候JVM才会回收该对象 |
弱引用 | WeakReference | 一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存 |
虚引用 | PhantomReference |
四种引用测试
private static class TestBean {
private String name;
public TestBean(String name) {
this.name = name;
}
@Override
protected void finalize() throws Throwable {
super.finalize();
p("finalize:" + this);
}
@Override
public String toString() {
return "TestBean{" +
"name='" + name + '\'' +
'}';
}
}
StrongReference
强引用是使用最普遍的引用。只要某个对象有强引用与之关联,JVM不会回收这个对象,即使在内存不足的情况下,JVM宁愿抛出OutOfMemory错误也不会回收这种对象.
TestBean testBean = new TestBean("强引用对象");
String str = "强引用对象";
testBean = null;//testBean 置为null后,就没有引用指向这个对象就可以被JVM回收内存
str = null;
SoftReference
软引用是用来描述一些有用但并不是必需的对象,在Java中用SoftReference类来表示。只有在内存不足的时候JVM才会回收该对象。
//测试测试软引用
private static void testSoftReference() {
TestBean testBean = new TestBean("Soft1"); //1创建对象“Soft1” ,通过testBean指向该对象 。这是强引用
ReferenceQueue<TestBean> referenceQueue = new ReferenceQueue<TestBean>(); //2创建引用队列,对象被回收,引用对象会被放进队列中
SoftReference<TestBean> reference = new SoftReference<TestBean>(testBean, referenceQueue);//3创建testBean对象的软引用
p("testBean:" + testBean + " reference:" + reference); //打印
testBean = null; //4 testBean引用置为null, 切断强引用
System.gc(); //5 触发GC
System.gc(); //6 触发GC
TestBean testBean1 = reference.get(); // 7假如testBean对象被回收,testBean1为null
p("testBean1:" + testBean1); //8打印对象
Reference ref = referenceQueue.poll(); //9如果testBean对象被回收,这个可以获取reference对象
p("ref:" + ref);//10打印reference
}
结果:
testBean:TestBean{name='Soft1'} reference:java.lang.ref.SoftReference@2503dbd3
testBean1:TestBean{name='Soft1'}
ref:null
可以看到,最终没有被回收,这个时候虽然只有软引用指向对象,发生GC的时候,也不一定会被回收掉。
内存模型如下:
当4执行过后,引用情况如下:
WeakReference
只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。
//测试弱引用
private static void testWeakReference() {
TestBean testBean = new TestBean("Weak1"); //1强引用
ReferenceQueue<TestBean> referenceQueue = new ReferenceQueue<TestBean>();
WeakReference<TestBean> reference = new WeakReference<TestBean>(testBean, referenceQueue); //2弱引用
p("testBean:" + testBean + " reference:" + reference);
testBean = null; //3切断强应用
System.gc(); //4 GC
TestBean testBean1 = reference.get(); // 假如testBean对象被回收,testBean1为null
p("testBean1:" + testBean1);
Reference ref = referenceQueue.poll(); //
p("ref:" + ref);
if (ref != null) {
p("ref.get:" + ref.get());
}
}
结果:
如果reference 指向的testBean 对象被回收的话,那么系统会把reference 加入到referenceQueue 队列中;可看出reference 被加入到了队列中,说明reference 指向的testBean 对象已经被回收了。
testBean:TestBean{name='Weak1'} reference:java.lang.ref.WeakReference@2503dbd3
testBean1:null //对象被回收
finalize:TestBean{name='Weak1'} //finalize方法被执行,该方法会在对象被回收的时候执行
ref:java.lang.ref.WeakReference@2503dbd3 //返回被回收的引用对象
ref.get:null //对象已经被回收了,打印null
模型如下:
开始的时候,"Weak1"内存区域有两个引用,强引用testBean,和弱引用reference。当切断强引用后,结果如下:
此时"Weak1"内存区域只有弱引用reference,当发生GC的时候就会被回收掉。
PhantomReference
待定