# 为什么会有这4中引用
Java中的引用的定义很传统：如果reference类型的数据中存储的数值代表的是另外一块内存的起始地址，就称这块内存代表着一个引用。 
这种定义很纯粹，但是太过狭隘，一个对象在这种定义下只有被引用或者没有被引用两种状态，对于如何描述一些“食之无味，弃之可惜”的
对象就显得无能为力。 我们希望能描述这样一类对象：当内存空间还足够时，则能保留在内存之中；如果内存空间在进行垃圾收集后还是
非常紧张，则可以抛弃这些对象。 很多系统的缓存功能都符合这样的应用场景。

说白了传统的两种应用没法描述对象生命周期中的多种状态，对象有哪些状态呢。

-----------------------------------------------------------------------------------------------------------------------

在Java中，对象的生命周期包括以下几个阶段：

创建阶段(Created)
应用阶段(In Use)
不可见阶段(Invisible)
不可达阶段(Unreachable)
收集阶段(Collected)
终结阶段(Finalized)
对象空间重分配阶段(De-allocated)

## 创建阶段(Created)
* 为对象分配存储空间
* 开始构造对象
* 从超类到子类对static成员进行初始化
* 超类成员变量按顺序初始化，递归调用超类的构造方法
* 子类成员变量按顺序初始化，子类构造方法调用
* 一旦对象被创建，并被分派给某些变量赋值，这个对象的状态就切换到了应用阶段

## 应用阶段(In Use)
对象至少被一个强引用持有着。

## 不可见阶段(Invisible)
当一个对象处于不可见阶段时，说明程序本身不再持有该对象的任何强引用，虽然该这些引用仍然是存在着的。
简单说就是程序的执行已经超出了该对象的作用域了。

## 不可达阶段(Unreachable)
对象处于不可达阶段是指该对象不再被任何强引用所持有。
与“不可见阶段”相比，“不可见阶段”是指程序不再持有该对象的任何强引用，这种情况下，该对象仍可能被JVM等系统下的某些已装载
的静态变量或线程或JNI等强引用持有着，这些特殊的强引用被称为”GC root”。存在着这些GC root会导致对象的内存泄露情况，无
法被回收。

## 收集阶段(Collected)
当垃圾回收器发现该对象已经处于“不可达阶段”并且垃圾回收器已经对该对象的内存空间重新分配做好准备时，则对象进入了“收集阶
段”。如果该对象已经重写了finalize()方法，则会去执行该方法的终端操作。
这里要特别说明一下：不要重载finazlie()方法！原因有两点：
###
会影响JVM的对象分配与回收速度
在分配该对象时，JVM需要在垃圾回收器上注册该对象，以便在回收时能够执行该重载方法；在该方法的执行时需要消耗CPU时间且在
执行完该方法后才会重新执行回收操作，即至少需要垃圾回收器对该对象执行两次GC
###
可能造成该对象的再次“复活”
在finalize()方法中，如果有其它的强引用再次持有该对象，则会导致对象的状态由“收集阶段”又重新变为“应用阶段”。这个已经
破坏了Java对象的生命周期进程，且“复活”的对象不利用后续的代码管理。

## 终结阶段
当对象执行完finalize()方法后仍然处于不可达状态时，则该对象进入终结阶段。在该阶段是等待垃圾回收器对该对象空间进行回收。

## 对象空间重新分配阶段
垃圾回收器对该对象的所占用的内存空间进行回收或者再分配了，则该对象彻底消失了，称之为“对象空间重新分配阶段”。

-----------------------------------------------------------------------------------------------------------------------

# 强引用
强引用是使用最普遍的引用。如果一个对象具有强引用，那垃圾收器绝不会回收它。当内存空间不足，Java虚拟机宁愿抛出
OutOfMemoryError错误，使程序异常终止，也不会靠随意回收具有强引用 对象来解决内存不足的问题。

# 软引用
软引用是用来描述一些还有用但并非必须的对象。对于软引用关联着的对象，在系统将要发生内存溢出异常之前，将会把这些对象列进
回收范围进行第二次回收。如果这次回收还没有足够的内存，才会抛出内存溢出异常。

# 弱引用
弱引用也是用来描述非必须对象的，他的强度比软引用更弱一些，被弱引用关联的对象，在垃圾回收时，如果这个对象只被弱引用关联
（没有任何强引用关联他），那么这个对象就会被回收。

# 虚引用
一个对象是否有虚引用的存在，完全不会对其生存时间构成影响，也无法通过虚引用来获取一个对象的实例。为一个对象设置虚引用关
联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。虚引用和弱引用对关联对象的回收都不会产生影响，如果只有虚引
用活着弱引用关联着对象，那么这个对象就会被回收。它们的不同之处在于弱引用的get方法，虚引用的get方法始终返回null,弱引
用可以使用ReferenceQueue,虚引用必须配合ReferenceQueue使用。
jdk中直接内存的回收就用到虚引用，由于jvm自动内存管理的范围是堆内存，而直接内存是在堆内存之外（其实是内存映射文件，自
行去理解虚拟内存空间的相关概念），所以直接内存的分配和回收都是有Unsafe类去操作，java在申请一块直接内存之后，会在堆
内存分配一个对象保存这个堆外内存的引用，这个对象被垃圾收集器管理，一旦这个对象被回收，相应的用户线程会收到通知并对直接
内存进行清理工作。
