背景
在jdk1.2以前,java对引用的定义和传统,只有引用和非引用之分。这种定义很纯粹,但是太过狭隘,一个对象在这种定义下,只有被引用或者没有被引用这两种状态,对于如何描述一些“食之无味,弃之可惜”的对象就显得无能为力。这时候推出了一种新的机制,强引用,弱引用,软引用和需虚引用
1.强引用(Stong Reference)
- 最普通的引用 Object o = new Object()
- 当内存空间不足时,java虚拟机抛出OutOfMemeoryError终止程序也不会回收具有强引用的对象
- 通过将对象设置为null来弱化引用,使其被回收
2.软引用 (Soft Reference)
- 对象处在有用但非必须的状态
- 只有当内存空间不足时,GC会回收该引用的对象的内存
使用场景说明: 软引用通常用来实现内存敏感的缓存。如果内存空间还有剩余,就可以暂时保留缓存,当内存不足时,就可以将缓存清除,这样就保证了使用缓存的同时,不会耗尽内存。
虚引用在实际中有重要的应用,例如浏览器的后退按钮。按后退时,这个后退时显示的网页内容是重新进行请求还是从缓存中取出呢?这就要看具体的实现策略了。
1.如果一个网页在浏览结束时就进行内容的回收,则按后退查看前面浏览过的页面时,需要重新构建
2. 如果将浏览过的网页存储到内存中会造成内存的大量浪费,甚至会造成内存溢出
Browser prev = new Browser(); // 获取页面进行浏览
SoftReference sr = new SoftReference(prev); // 浏览完毕后置为软引用
if(sr.get()!=null){
rev = (Browser) sr.get(); // 还没有被回收器回收,直接获取
}else{
prev = new Browser(); // 由于内存吃紧,所以对软引用的对象回收了
sr = new SoftReference(prev); // 重新构建
}
这就很好的解决了实际问题!
3.弱引用(Weak Reference)
- 非必需的对象,比软引用更弱。
- GC时会被回收
- 由于垃圾回收是一个优先级很低的线程,被回收的概率也不大。
4.虚引用(PhantomReference)
- 不会决定对象的声明周期
- 任何时候都可能被垃圾收集器回收
- 用于跟踪对象被垃圾收集器回收的活动,起哨兵作用
- 必须和引用队列ReferenceQueue联合使用
使用场景:(跟踪对象被垃圾回收器回收):
比如现在我们需要判断一个对象是否被垃圾回收了
1.给这个对象创建一个虚引用
2.加入虚引用到引用队列中
3.判断引用队列是否有该对象,如果有,将要被回收。
当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。
5.引用队列(ReferenceQueue)
在软引用,弱引用,需引用被回收对象内存之前,会将对应的引用加入到引用队列中。