- 强引用
创建一个对象,让一个引用变量指向该对象,该引用变量就是强引用,处于可达的状态,是不可能被垃圾回收期机制回收的,,如果一个对象没有被引用对象指向,可认为是可以被回收的。只要有引用变量指向,都不会回收。
@Test
public void test01() {
Object obj1=new Object();
Object obj2=obj1;
obj1=null;
//垃圾回收
System.gc();
//照常输出obj2指向的对象
System.out.println(obj2);
}
代码中创建了obj1 obj2引用变量,obj1指向null,执行垃圾回收,打印obj2的结果,发现依然是开始的对象,创建引用变量,然后指向分配的对象,为强引用,只要还有引用变量指向,就不会被垃圾回收器收集。
- 软引用
SoftReference
如果内存够不会被回收,如果内存不够了,将会被回收。
测试代码
/**
* 软引用
* 添加jvm参数 -Xms5m -Xmx5m -XX:+PrintGCDetails -XX:+PrintCommandLineFlags
*/
@Test
public void test02() {
Object obj1 = new Object();
SoftReference<Object> softReference = new SoftReference<Object>(obj1);
System.out.println(obj1);
System.out.println(softReference.get());
obj1 = null;
try {
// 分配30M的内存空间
byte[] bytes = new byte[30 * 1024 * 1024];
} finally {
//null
System.out.println(obj1);
//null
System.out.println(softReference.get());
}
}
创建obj1应用变量,然后赋值给软应用,然后让obj1不指向new 的对象。分配超过堆内存空间的数组。打印软引用。
适合缓存很多数据,同时避免出现OOM。
- 弱引用
WeakReference
不管内存够不够,下次发生GC都会被回收。
@Test
public void test03() {
WeakReference<Object> softReference = new WeakReference<Object>(new Object());
//java.lang.Object@65e2dbf3
System.out.println(softReference.get());
System.gc();
//打印null,已经被回收了。
System.out.println(softReference.get());
}
使用案例WeakHashMap
@Test
public void test05() {
WeakHashMap<Integer, String> map=new WeakHashMap<>();
Integer key=new Integer(1);
String value="WeakHashMap";
map.put(key, value);
//{1=WeakHashMap}
System.out.println(map);
key=null;
//{1=WeakHashMap}
System.out.println(map);
System.gc();
//{} 1
System.out.println(map+" "+map.size());
}
key指向的内存空间如果没有其他引用变量指向该处,那么指向gc的时候将会把该键值对回收。
-
虚引用
PhantomReference
如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能会被垃圾回收器回收掉。 -
引用队列
@Test
public void test07() throws InterruptedException {
Object obj1=new Object();
ReferenceQueue<Object> referenceQueue=new ReferenceQueue<>();
PhantomReference<Object> phantomReference=new PhantomReference<Object>(obj1,
referenceQueue);
//java.lang.Object@65e2dbf3
System.out.println(obj1);
//null
System.out.println(phantomReference.get());
//null
System.out.println(referenceQueue.poll());
obj1=null;
System.out.println("-----------gc-------------");
System.gc();
Thread.sleep(2000);
//null
System.out.println(obj1);
//null
System.out.println(phantomReference.get());
//true
System.out.println(referenceQueue.poll()==phantomReference);
}
引用在被回收之前会被被放到引用队列。 \color{#FF0000}{引用在被回收之前会被被放到引用队列。} 引用在被回收之前会被被放到引用队列。 如果队列中有数据,那么说明发生了gc回收,JVM允许我们在垃圾回收之前做我们想做的事情。