1、从JDK1.2开始,Java在Java.lang.ref包下提供了3个类:SoftReference、PhantomReference和WeakReference。它们分别代表了系统对对象的3种引用方式:软引用、虚引用和弱引用。归纳起来,Java语言对对象的引用有如下4种:强引用、软引用、弱引用、虚引用。
2、强引用:
①这是Java程序中最常见的引用方式,程序创建一个对象,并把这个对象赋给一个引用变量,这个引用变量就是强引用。
②Java程序可通过强引用来访问实际的对象。 当一个对象被一个或一个以上的强引用变量所引用时,它初处于可达状态,它不可能被系统垃圾回收机制回收。
③强引用是Java变成中广泛使用的引用类型,被强引用所引用的西乡绝不会被垃圾回收机制回收,即使系统内存非常紧张,即使有些Java对象以后永远都不会被用到,JVM也不会回收被强引用所引用的Java对象。
④由于JVM肯定不会回收强引用所引用的Java对象,因此强引用是造成Java内存泄露的主要原因之一。
3、软引用:
①软引用需要通过SoftReference类来实现,当一个对象只具有软引用时,它又可能被垃圾回收机制回收。对于只有软引用的对象而言,当系统内存空间足够时,它不会被系统回收,程序也可使用该对象;当系统内存空间不足时,系统将会回收它。
②软引用通常用于对内存敏感的程序中,软引用是强引用很好的替代。对于被强引用所引用的Java对象而言,无论系统的内存如何紧张,即使某些Java对象以后再也不可能使用,垃圾回收机制依然不会回收它所占用的内存。对于软引用则不同,当系统内存空间充足时,软引用与强引用没有太大的区别;当系统内存空间不足时,被软引用所引用的Java对象可以被垃圾回收机制回收,从而避免系统内存不足的异常。
③当程序需要大量创建某个类的新对象,而且有可能重新访问已创建老对象时可以充分使用软引用来解决内存紧张的问题。
如下一段程序,运行时带上参数限制堆的大小:-Xms2m-Xmx2m(逐渐会超过2m,很奇怪)
class Person {
private String name;
private int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String toString() {
return "Person[name=" + name + ",age=" + age + "]";
}
}
@SuppressWarnings("unchecked")
public class TestReference {
public static void main(String args[]) {
SoftReference<Person>[] people = new SoftReference[60000];
for (int i = 0; i < people.length; i++) {
people[i] = new SoftReference<Person>(new Person("test" + i, i));
}
System.out.println("people[2] = " + people[2].get());
System.out.println("people[4] = " + people[4].get());
// 通知系统进行垃圾回收
System.gc();
System.runFinalization();
// 垃圾回收机制运行之后,SoftReference数组里的元素保持不变
System.out.println("people[2] = " + people[2].get());
System.out.println("people[9999] = " + people[59999].get());
}
}
输出结果:
people[2]= null
people[4]= null
people[2]= null
people[9999]= Person[name=test59999,age=59999]
我们会发现people[2]和people[4]已经被回收了,因为new了60000个Person对象,系统内存不足。我们可以在运行过程中把GC打印出来看看:(为什么堆内存大于2m了)
可以看出此时系统内存紧张,所以作为软引用之前的已经被回收了。
如果之前声明的是强引用,那么这里是不会回收的,所以可能导致程序因内存不足而报出OutOfMemoryError: Java heap space这样的错误。但如果把强引用改为使用软引用,就可完全避免这种情况,这就是软引用的优势所在。
另外2种引用明天再写。。。