一.强引用
即普通引用,我们正常使用对象时即为强引用。当我们没有引用指向new出来的对象的时候,M才会被垃圾回收器回收。
class M{
protected void finalize() throws Throwable{
System.out.println("finalize");
}
}
public class demo {
public static void main(String[] args) throws IOException {
M m = new M();
//给m赋空值,即没有引用指向M对象了,这时
m=null;
//这时调用gc(),M对象就会被回收
System.gc();
System.in.read();
}
}
说一下M类中的finalize的方法。这个方法重写会引起严重的GC问题,产生OOM问题(out of memory)所以一般别重写。‘
那么finalize的方法有什么作用呢?
在垃圾回收的时候此方法会被调用,那么如果执行打印了此方法中的语句,就说明M对象被回收了。
这个就是强引用的引用和对象的关系。
二.软引用:非常适合于缓存使用
当分配的堆内存不够用时,软引用会被回收。
public class demo2 {
public static void main(String[] args) {
//这时相当于有两个引用。
SoftReference<byte[]> m = new SoftReference<byte[]>(new byte[1024*1024*10]);
//m.get()是取到数组的内容
System.out.println(m.get());
System.gc();
System.out.println(m.get());
//再分配一个数组,内存大小为15M,这时10+15已经超过了限定的
//堆内存大小,所以这时候会被垃圾回收器回收
byte[] b = new byte[1024*1024*15];
System.out.println(m.get());
}
}
此时有两个引用。内存不够用了软引用会被回收。
这个程序,在运行时,是带参数的,步骤run—>Edit—>VM options:(-Xmx20M)。这个参数的意思是将堆内存设为固定的为20M.以此来演示软引用被回收的情况。
上边代码有三个输出:
打印为:1.数组对象(调用gc也不回收)
2.数组对象//(调用gc此时没有被回收)
3.null //此时内存已经不够用了 所以被回收。打印为null
应用场景:有一个特别大的图片,想放在内存,但是它太大了占地方;拿走,用的时候再拿过来又得load效率太低了。
那么把它放到一个缓存中(用一个软引用指向这个图片,相当于上边程序的数组对象),然后正常使用,如果内存不够用时,它就会被回收。这样做兼顾了时间和空间的效率。