java强引用,软引用,弱引用,虚引用

用了Java怎么长时间一直不知道原来Java还有四种引用类型,这个引用类型和我们平常说的可不一样。这里的引用类型不是指数据类型的一种,而是指Java中的引用所分的四种类型。他们代表了JVM回收内存的四种强度,分别如下。

强引用:

Java中的引用,有点像C++的指针。通过引用,可以对堆中的对象进行操作。在某函数中,当创建了一个对象,该对象被分配在堆中,通过这个对象的引用才能对这个对象进行操作。

Object o=new Object();

假设以上代码是在函数体内运行的,那么局部变量o将被分配在栈上,而对象实例,被分配在堆上。局部变量o指向Object实例所在的堆空间,通过o可以操作该实例,那么o就是Object的引用。


如果再创建一个赋值语句

Object oj=o;

那么o指向的Object内存空间也会被oj所指向,此时我们可以说oj==o,那么ob.equals也肯定相等,即两个对象的值也肯定一样,当修改了o对象的时候,oj对象也会发生变化,或者当修改了oj对象的时候o对象也肯定会变化。所以如果想复制另外一个对象的值的话千万不要用这种方式,在多线程的情况下可能会有更槽糕的情况发生,你可以使用JDK自带的克隆方法,也可以重写克隆方法。

public class Test1 {
			public static void main(String[] args) {
				student S=new student("1","我是大s");
				student s=S;
				System.out.println(s==S); //true
				System.out.println(s.equals(S)); //true
				System.out.println("打印出大S"+S); //id=1
				System.out.println("打印出小s"+s); //id=1
				S.setId("2");
				System.out.println("修改后的大S"+S);  //id=2
				System.out.println("未修改后的小s"+s); //id=2
				s.setId("3");
				System.out.println("未修改后的大S"+S); //id=3
				System.out.println("修改后的小s"+s); //id=3

			}
}
class student{
	String name;
	String id;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public student(String name, String id) {
		super();
		this.name = name;
		this.id = id;
	}
	@Override
	public String toString() {
		return "student [name=" + name + ", id=" + id + "]";
	}

}

上例中的大S和小S都是强引用,强引用具有如下特点:

1.强引用可以直接访问目标对象。

2.强引用所指向的对象在任何时候都不会被系统回收。JVM宁愿抛出OOM异常,也不会回收强引用所指向的对象。

3.强引用可能导致内存泄漏,为了避免内存泄漏,在使用完成之后我们可以把字符串对象设置为null,如果是集合的话可以使用

List list=new ArrayList<>();
list.clear();

软引用:

软引用的强度是仅次于强引用的,如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。

我们可以使用java.lang.ref.SoftReference来创建软引用;

String str=new String("abc");                                     // 强引用
SoftReference<String> softRef=new SoftReference<String>(str);     // 软引用

当内存不足时,等价于:

If(JVM.内存不足()) {
   str = null;  // 转换为软引用
   System.gc(); // 垃圾回收器进行回收
}

弱引用:

弱引用的强度比软引用更次,也就是说只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。

如果这个对象是偶尔的使用,并且希望在使用时随时就能获取到,但又不想影响此对象的垃圾收集,那么你应该用 Weak Reference 来标记此对象。

String str=new String("abc");
WeakReference<String> abcWeakRef = new WeakReference<String>(str);
str=null;

如果你想把这个对象变成强引用的话可以使用

String  abc = abcWeakRef.get();

弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。

当你想引用一个对象,但是这个对象有自己的生命周期,你不想介入这个对象的生命周期,这时候你就是用弱引用。

这个引用不会在对象的垃圾回收判断中产生任何附加的影响。

public class ReferenceTest {

	private static ReferenceQueue<VeryBig> rq = new ReferenceQueue<VeryBig>();

	public static void checkQueue() {
		Reference<? extends VeryBig> ref = null;
		while ((ref = rq.poll()) != null) {
			if (ref != null) {
				System.out.println("In queue: "	+ ((VeryBigWeakReference) (ref)).id);
			}
		}
	}

	public static void main(String args[]) {
		int size = 3;
		LinkedList<WeakReference<VeryBig>> weakList = new LinkedList<WeakReference<VeryBig>>();
		for (int i = 0; i < size; i++) {
			weakList.add(new VeryBigWeakReference(new VeryBig("Weak " + i), rq));
			System.out.println("Just created weak: " + weakList.getLast());

		}

		System.gc();
		try { // 下面休息几分钟,让上面的垃圾回收线程运行完成
			Thread.currentThread().sleep(6000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		checkQueue();
	}
}

class VeryBig {
	public String id;
	// 占用空间,让线程进行回收
	byte[] b = new byte[2 * 1024];

	public VeryBig(String id) {
		this.id = id;
	}

	protected void finalize() {
		System.out.println("Finalizing VeryBig " + id);
	}
}

class VeryBigWeakReference extends WeakReference<VeryBig> {
	public String id;

	public VeryBigWeakReference(VeryBig big, ReferenceQueue<VeryBig> rq) {
		super(big, rq);
		this.id = big.id;
	}

	protected void finalize() {
		System.out.println("Finalizing VeryBigWeakReference " + id);
	}
}

虚引用

虚引用顾名思义就是形同虚设,虚引用也称为幻影引用:一个对象是都有虚引用的存在都不会对生存时间都构成影响,也无法通过虚引用来获取对一个对象的真实引用。唯一的用处:能在对象被GC时收到系统通知,JAVA中用PhantomReference来实现虚引用。

对比不同:

class Grocery {
		private static final int SIZE = 10000;
		// 属性d使得每个Grocery对象占用较多内存,有80K左右
		private double[] d = new double[SIZE];
		private String id;
		public Grocery(String id) {
			this.id = id;
		}
		public String toString() {
			return id;
		}
		public void finalize() {
			System.out.println("即将回收 " + id);
		}
	}
	public class References {
		private static ReferenceQueue<Grocery> rq = new ReferenceQueue<Grocery>();
		public static void checkQueue() {
			Reference<? extends Grocery> inq = rq.poll(); // 从队列中取出一个引用
			if (inq != null)
				System.out.println("In queue: " + inq + " : " + inq.get());
		}
		public static void main(String[] args) {
			final int size = 10;
			// 创建10个Grocery对象以及10个软引用
			Set<SoftReference<Grocery>> sa = new HashSet<SoftReference<Grocery>>();
			for (int i = 0; i < size; i++) {
				SoftReference<Grocery> ref = new SoftReference<Grocery>(
						new Grocery("软引用 " + i), rq);
				System.out.println("刚刚 创建了: " + ref.get());
				sa.add(ref);
			}
			System.gc();
			checkQueue();
			// 创建10个Grocery对象以及10个弱引用
			Set<WeakReference<Grocery>> wa = new HashSet<WeakReference<Grocery>>();
			for (int i = 0; i < size; i++) {
				WeakReference<Grocery> ref = new WeakReference<Grocery>(
						new Grocery("弱引用 " + i), rq);
				System.out.println("刚刚 创建了: " + ref.get());
				wa.add(ref);
			}
			System.gc();
			checkQueue();
			// 创建10个Grocery对象以及10个虚引用
			Set<PhantomReference<Grocery>> pa = new HashSet<PhantomReference<Grocery>>();
			for (int i = 0; i < size; i++) {
				PhantomReference<Grocery> ref = new PhantomReference<Grocery>(
						new Grocery("abc " + i), rq);
				System.out.println("刚刚 创建了: " + ref.get());
				pa.add(ref);
			}
			System.gc();
			checkQueue();
		}
}

在上面的这个例子中,依次创建了十个10个软引用、10个弱引用和10个虚引用,它们各自引用一个Grocery对象。并且在创建之后调用GC方法。从程序运行时的打印结果可以看出,虚引用形同虚设,它所引用的对象随时可能被垃圾回收,具有弱引用的对象拥有稍微长的生命周期,当垃圾回收器执行回收操作时,有可能被垃圾回收,具有软引用的对象拥有较长的生命周期,但在Java虚拟机认为内存不足的情况下,也会被垃圾回收。

总结

强引用:就像是老板(OOM)的亲儿子一样,在公司可以什么事都不干,但是千万不要老是占用公司的资源为他自己做事,记得用完公司的妹子之后,要让她们去工作(资源要懂得释放) 不然公司很可能会垮掉的。
软引用:有点像老板(OOM)的亲戚,在公司表现不好有可能会被开除,即使你投诉他(调用GC)上班看片,但是只要不被老板看到(被JVM检测到)就不会被开除(被虚拟机回收)。
弱引用:就是一个普通的员工,平常如果表现不佳会被开除(对象没有其他引用的情况下),遇到别人投诉(调用GC)上班看片,那开除是肯定了(被虚拟机回收)。
虚引用:这货估计就是个实习生跟临时工把,遇到事情的时候想到了你,没有事情的时候,秒秒钟拿出去顶锅,开除。

时间: 2024-10-22 03:21:40

java强引用,软引用,弱引用,虚引用的相关文章

java中四种引用类型(对象的强、软、弱和虚引用)

对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK 1.2版本开始,把对象的引用分为4种级别,从而使程序能更加灵活地控制对象的生命周期.这4种级别由高到低依次为:强引用.软引用.弱引用和虚引用. ⑴强引用(StrongReference) 强引用是使用最普遍的引用.如果一个对象具有强引用,那垃圾回收器绝不会回收它.当内存空间不足,Java虚拟机宁愿抛出O

Java:对象的强、软、弱和虚引用(转)

1.对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK 1.2版本开始,把对象的引用分为4种级别,从而使程序能更加灵活地控制对象的生命周期.这4种级别由高到低依次为:强引用.软引用.弱引用和虚引用.图1为对象应用类层次. 图1 ⑴强引用(StrongReference) 强引用是使用最普遍的引用.如果一个对象具有强引用,那垃圾回收器绝不会回收它.当内存空

Java中强、软、弱、虚引用

一.前言 忘记之前是怎么接触到Java的强.软.弱.虚引用的了,恍恍惚惚好像是在看垃圾回收的时候,略过了这些个概念~这些知识在平时开发中使用的真是少之又少(也许我的level还不够)~今天就将这些整理完毕吧~ 二.正文 对于Java中这几种引用的理解,有助于理解JVM的回收内存的机制.先说下在JVM执行垃圾回收时,如何处理它们所引用的对象: 1)强引用,任何时候都不会被垃圾回收器回收,如果内存不足,宁愿抛出OutOfMemoryError. 2)软引用,只有在内存将满的时候才会被垃圾回收器回收,

Java:对象的强、软、弱和虚引用

本文介绍对象的强.软.弱和虚引用的概念.应用及其在UML中的表示. author: ZJ 07-12-1 Blog: [url]http://zhangjunhd.blog.51cto.com/[/url] 1.对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK 1.2版本开始,把对象的引用分为4种级别,从而使程序能更加灵活地控制对象的生命周期.这4种级

Java对象的强、软、弱和虚引用原理+结合ReferenceQueue对象构造Java对象的高速缓存器

//转 http://blog.csdn.net/lyfi01/article/details/6415726 1.Java对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.这 就像在日常生活中,从商店购买了某样物品后,如果有用,就一直保留它,否则就把它扔到垃圾箱,由清洁工人收走.一般说来,如果物品已经被扔到垃圾箱,想再 把它捡回来使用就不可能了. 但有时候情况

java基础知识再学习--集合框架-对象的强、软、弱和虚引用

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://zhangjunhd.blog.51cto.com/113473/53092 本文介绍对象的强.软.弱和虚引用的概念.应用及其在UML中的表示. author: ZJ 07-12-1 Blog: [url]http://zhangjunhd.blog.51cto.com/[/url] 1.对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序

强、软、弱和虚引用的概念

本文介绍对象的强.软.弱和虚引用的概念.应用及其在UML中的表示. 1.对象的强.软.弱和虚引用   在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK 1.2版本开始,把对象的引用分为4种级别,从而使程序能更加灵活地控制对象的生命周期.这4种级别由高到低依次为:强引用.软引用.弱引用和虚引用.图1为对象应用类层次. 图1 ⑴强引用(StrongReference)    强引用

【转】对象的强、软、弱和虚引用

对象的强.软.弱和虚引用在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK 1.2版本开始,把对象的引用分为4种级别,从而使程序能更加灵活地控制对象的生命周期.这4种级别由高到低依次为:强引用.软引用.弱引用和虚引用. ⑴强引用(StrongReference)强引用是使用最普遍的引用.如果一个对象具有强引用,那垃圾回收器绝不会回收它.当内存空间不足,Java虚拟机宁愿抛出Out

详解Java中对象的软、弱和虚引用的区别

对于大部分的对象而言,程序里会有一个引用变量来引用该对象,这是最常见的引用方法.除此之外,java.lang.ref包下还提供了3个类:SoftReference.WeakReference和PhantomReference.它们分别代表了系统对对象的另外3中引用方式:软引用.弱引用和虚引用. Java中四种引用的区别和关联: 强引用.这是Java中最常见的引用方式.程序创建一个对象,并把这个对象赋给一个引用变量,程序通过该引用变量来操作实际的对象.当一个对象被一个或者多个引用变量引用时,它处于

4中引用(强,软,弱,虚)侧重弱引用

1,强引用,对象有强引用与之关联,即使在内存不足,抛出OutOfMemory错误也不会回收这种对象 2,软引用是用来描述一些有用但并不是必需的对象,java.lang.ref.SoftReference类来表示. 对于软引用关联着的对象,只有在内存不足的时候JVM才会回收该对象.可以很好地用来解决OOM的问题,适合用来实现缓存:比如网页缓存.图片缓存等. 软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被JVM回收,这个软引用就会被加入到与之关联的引用队列