强引用
强引用是最传统的“引用”的定义,是指在程序代码之中普遍存在的引用赋值,即类似“Objectobj=newObject()”这种引用关系。无论任何情况下,只要强引用关系还存在,垃圾收集器就永远不会回收掉被引用的对象。
软引用
软引用是用来描述一些还有用,但非必须的对象。只被软引用关联着的对象,在系统将要发生内存溢出异常前,会把这些对象列进回收范围之中进行第二次回收,如果这次回收还没有足够的内存,才会抛出内存溢出异常。在JDK1.2版之后提供了SoftReference类来实现软引用。
/**
* @Author: hqh
* @Email: ****
* @Date: 2021/5/13 17:05
* @VMOptions: -Xms10m -Xmx10m -XX:+PrintGC
*/
public class SoftRef {
/**
* User{name='soft'}
* [GC (System.gc()) 1740K->688K(9728K), 0.0009848 secs]
* [Full GC (System.gc()) 688K->626K(9728K), 0.0046709 secs]
* after gc User{name='soft'}
* ********User{name='soft'}
* ********User{name='soft'}
* [GC (Allocation Failure) 4831K->4914K(9728K), 0.0004184 secs]
* [GC (Allocation Failure) 4914K->4850K(9728K), 0.0001899 secs]
* [Full GC (Allocation Failure) 4850K->4715K(9728K), 0.0055943 secs]
* [GC (Allocation Failure) 4715K->4715K(9728K), 0.0003602 secs]
* [Full GC (Allocation Failure) 4715K->4697K(9728K), 0.0052976 secs]
* Java heap space
* OOM++++++++++null
* @param args
*/
public static void main(String[] args) {
User user = new User("soft");
SoftReference<User> userSoftReference = new SoftReference<>(user);
//干掉强引用
user=null;
System.out.println(userSoftReference.get());
System.gc();
System.out.println("after gc "+userSoftReference.get());
List<Byte[]> list = new LinkedList<>();
try{
for (int i = 0; i < 100; i++) {
System.out.println("********"+userSoftReference.get());
list.add(new Byte[1024*1024*1]);
}
}catch (Throwable e){
System.out.println(e.getMessage());
System.out.println("OOM++++++++++"+userSoftReference.get());
}
}
}
class User{
private String name;
public User(String name){
this.name=name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
弱引用
弱引用也是用来描述那些非必须对象,但是它的强度比软引用更弱一些,被弱引用关联的对象只能生存到下一次垃圾收集发生为止。当垃圾收集器开始工作,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。在JDK1.2版之后提供了WeakReference类来实现弱引用。
ThreadLocal中ThreadLocalMap中Entity 使用了弱引用。
/**
* User{name='soft'}
* [GC (System.gc()) 1740K->696K(9728K), 0.0008714 secs]
* [Full GC (System.gc()) 696K->626K(9728K), 0.0039836 secs]
* null
* @param args
*/
public static void main(String[] args) {
User user = new User("soft");
WeakReference<User> weakReference = new WeakReference<>(user);
//去掉强引用
user=null;
System.out.println(weakReference.get());
System.gc();
System.out.println(weakReference.get());
}
}
虚引用
它是最弱的一种引用关系。一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的唯一目的只是为了能在这个对象被收集器回收时收到一个系统通知。在JDK1.2版之后提供了PhantomReference类来实现虚引用。