当我在写一个程序的时候,定义成员变量、写某个方法、定义局部变量、new对象的时候,这到底背后发生了什么?由此引发了JVM的内存模型。
这里我用箭头表示引发的一系列思考:JVM内存模型—>重点关注堆内存—>GC回收算法—>引用的四种类型。
强引用 :首先当 Object obj = new Object();当我使用new关键字的时候,就是一种强引用,表示任何时候都不会被回收。
软引用 :在java.lang.ref包下,有SoftReference类,当内存不足的时候,会被GC回收。
弱引用 :在java.lang.ref包下,有WeakReference类,是相对软引用来讲的,只要存在弱引用对象,那么不管内存是否足够,一定会被回收;
虚引用 :在java.lang.ref包下,有PhantomReference类,其顾名思义,形同虚设,任何时候都有可能被回收。;
看到这张图,大家可以联想到什么呢?
|
|
|
有没有想到Java的访问修饰符啊,同样给出图片
好了接下来,来分析源码,这里以SoftReference为例
import java.lang.ref.SoftReference;
public class SoftReferenceTest {
public static void main(String[] args) {
String str = new String("强引用");
SoftReference softReference = new SoftReference(str);
System.out.println("输出软引用:" + softReference);**加粗样式**
}
}
package cn.fortune;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
/**
* @author Mark Reinhold
* @since 1.2
*/
public class SoftReference extends Reference {//这里继承Reference
/**
* Timestamp clock, updated by the garbage collector
*/
static private long clock;
/**
* Timestamp updated by each invocation of the get method. The VM may use
* this field when selecting soft references to be cleared, but it is not
* required to do so.
*/
private long timestamp;
/**
* Creates a new soft reference that refers to the given object. The new
* reference is not registered with any queue.
*
* @param referent object the new soft reference will refer to
*/
public SoftReference(T referent) {
super(referent);
this.timestamp = clock;
}
/**
* Creates a new soft reference that refers to the given object and is
* registered with the given queue.
*
* @param referent object the new soft reference will refer to
* @param q the queue with which the reference is to be registered,
* or null if registration is not required
*
*/
public SoftReference(T referent, ReferenceQueue super T> q) {
super(referent, q);
this.timestamp = clock;
}
/**
* Returns this reference object's referent. If this reference object has
* been cleared, either by the program or by the garbage collector, then
* this method returns null
.
*
* @return The object to which this reference refers, or
* null
if this reference object has been cleared
*/
public T get() {//这里是最最要的方法
T o = super.get();
if (o != null && this.timestamp != clock)
this.timestamp = clock;
return o;
}
}
进一步,我再看一下,Reference这个类,具体信息(这里还可以看到两个关键字voliate与transient,大家知道它的用法吗?):
package cn.fortune;
import sun.misc.Cleaner;
import java.lang.ref.ReferenceQueue;
/**
* @author Mark Reinhold
* @since 1.2
*/
public abstract class Reference {
private T referent; /* Treated specially by GC */
volatile ReferenceQueue super T> queue;
Reference next;
transient private Reference discovered; /* used by VM */
/* Object used to synchronize with the garbage collector. The collector
* must acquire this lock at the beginning of each collection cycle. It is
* therefore critical that any code holding this lock complete as quickly
* as possible, allocate no new objects, and avoid calling user code.
*/
static private class Lock { };
private static Lock lock = new Lock();
/* List of References waiting to be enqueued. The collector adds
* References to this list, while the Reference-handler thread removes
* them. This list is protected by the above lock object. The
* list uses the discovered field to link its elements.
*/
private static Reference
软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。
补充一下:
软引用主要用户实现类似缓存的功能,在内存足够的情况下直接通过软引用取值,无需从繁忙的真实来源查询数据,提升速度;当内存不足时,自动删除这部分缓存数据,从真正的来源查询这些数据。
弱引用主要用于监控对象是否已经被垃圾回收器标记为即将回收的垃圾,可以通过弱引用的isEnQueued方法返回对象是否被垃圾回收器标记。
虚引用是每次垃圾回收的时候都会被回收,通过虚引用的get方法永远获取到的数据为null,因此也被成为幽灵引用。
虚引用主要用于检测对象是否已经从内存中删除。
参考文献
[1]: https://blog.csdn.net/u010325193/article/details/80284444
[2]: https://www.cnblogs.com/yw-ah/p/5830458.html