jvm 07-java引用类型

java引用类型

  • 强引用:当内存不足的时候,都不会进行空间回收,最终JVM抛出OutOfMemoryError
  • 软引用:当内存不足的时候,进行对象的回收处理,往往用于高速缓存中
  • 弱引用:不管内存是否紧张,只要GC运行都会回收
  • 幽灵引用:和没引用一样。

强引用

  • JVM默认支持模式
  • 在引用期间内,如果该堆内存被指定的栈内存有联系,那该对象就无法被GC所回收
  • 一旦出现内存不足,就会出现OutOfMemoryError异常
  • 正因为强引用具备内存分配异常问题,因此尽量少实例化对象

测试程序:

package cn.liang.jvm;
import static org.hamcrest.CoreMatchers.nullValue;
import java.lang.ref.SoftReference;
public class referenceType2 {
	public static void main(String[] args) {
		Object object = new Object();
		Object ref = object;
		object = null;
		System.out.println("内存充足时进行gc回收:");
		System.gc();
		System.out.println(ref);
		System.out.println("内存不足时进行gc回收:");
		try {
			String string = "liangjingfu";
			while (true) {
				string += string + string;
				string.intern();	
			}
		} catch (Throwable e) {
		}
		System.out.println(ref);
	}
}

输出结果:

内存充足时进行gc回收:
java.lang.Object@7852e922
内存不足时进行gc回收:
java.lang.Object@7852e922

软引用

  • 在许多的开源组件中,往往会使用软引用作为缓存组件出现
  • 软引用不足时回收,不充足时不回收
  • 软引用需要一个单独的类来实现控制:java.lang.ref.SoftReference
    • 构造函数:public SoftReference(T referent)
    • 取出数据:public T get();

测试程序:

package cn.liang.jvm;
import static org.hamcrest.CoreMatchers.nullValue;
import java.lang.ref.SoftReference;
public class referenceType2 {
	public static void main(String[] args) {
		Object object = new Object();
		SoftReference<Object> ref = new SoftReference<Object>(object);
		object = null;
		System.out.println("内存充足时进行gc回收:");
		System.gc();
		System.out.println(ref.get());
		System.out.println("内存不足时进行gc回收:");
		try {
			String string = "liangjingfu";
			while (true) {
				string += string + string;
				string.intern();	
			}
		} catch (Throwable e) {
		}
		System.out.println(ref.get());
	}
}

输出结果:

内存充足时进行gc回收:
java.lang.Object@7852e922
内存不足时进行gc回收:
null

弱引用:

  • 只要一进行GC处理,那么所引用的对象将会立即回收
  • 弱引用需要使用Map接口的子类:java.util.WeakHashMap
  • java.lang.ref包中存在一个WeakReference子类

测试程序1:

package cn.liang.jvm;
import java.util.Map;
import java.util.WeakHashMap;
public class referenceType3 {
	public static void main(String[] args) {
		String keyString = new String("name");
		String valueString = new String("liang");
		Map<String, String> map = new WeakHashMap<String, String>();
		map.put(keyString, valueString);
		keyString = null;
		System.out.println("内存进行gc回收前:");
		System.out.println(map);
		System.out.println("内存进行gc回收后:");
		System.gc();
		System.out.println(map);
	}
}

输出结果:

内存进行gc回收前:
{name=liang}
内存进行gc回收后:
{}

测试程序2:

package cn.liang.jvm;
import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.WeakHashMap;
public class referenceType3 {
	public static void main(String[] args) {
		String keyString = new String("liang");
		WeakReference<String> reference = new WeakReference<String>(keyString);
		keyString = null;
		System.out.println("内存进行gc回收前:");
		System.out.println(reference.get());
		System.gc();
		System.out.println("内存进行gc回收后:");
		System.out.println(reference.get());
	}
}

输出结果:

内存进行gc回收前:
liang
内存进行gc回收后:
null

引用队列

  • 主要是保存那些准备被回收的对象
  • 所有的对象的回收扫描都是从根对象开始的
  • 引用路径的设置即确定好哪些对象可以被回收后,设置相应的引用强度
  • 引用队列可避免非强引用对象所带来的内存引用问题,该对象被回收后会自动保存
  • 找到对象5有两个路径:
    • 对象1 --> 对象5(强 + 软)
    • 对象2 --> 对象5(强 + 弱)

测试程序:

package cn.liang.jvm;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.WeakHashMap;
public class referenceType4 {

	public static void main(String[] args) throws Exception {
		Object obj = new Object();
		ReferenceQueue<Object> queue = new ReferenceQueue<Object>();
		WeakReference<Object> reference = new WeakReference<Object>(obj,queue);
		System.out.println("内存进行gc回收前:");
		System.out.println(queue.poll());
		obj = null;
		System.gc();
		Thread.sleep(100);
		System.out.println("内存进行gc回收后,对象保存:");
		System.out.println(queue.poll());
	}
}

输出结果:

内存进行gc回收前:
null
内存进行gc回收后,对象保存:
java.lang.ref.WeakReference@7852e922

幽灵引用

  • 永远取不了的数据

测试程序:

package cn.liang.jvm;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.WeakHashMap;
public class referenceType5 {
	public static void main(String[] args) throws Exception {
		Object obj = new Object();
		ReferenceQueue<Object> queue = new ReferenceQueue<Object>();
		PhantomReference<Object> reference = new PhantomReference<Object>(obj,queue);
		System.gc();
		System.out.println("对象读取:");
		System.out.println(reference.get());
		System.out.println("对象保存后读取:");
		System.out.println(queue.poll());
	}
}

输出结果:

对象读取:
null
对象保存后读取:
null
posted @ 2018-11-26 11:01  瞎搞的富哥  阅读(265)  评论(0编辑  收藏  举报