记录Java的垃圾回收机制和几种引用

一.Java的垃圾回收机制java

  Java的垃圾回收机制(java garbage collection)是Java虚拟机提供的能力,用于在空闲时间以不定时的方式动态回收无任何引用的对象占据的堆内存空间。编程

  注意粗体字的地方,java的垃圾回收线程是优先级比较低的线程,何时进行垃圾回收难以肯定。当某些对象被标记为垃圾对象后,等垃圾回收线程运行时,就会将这些对象回收(确切的说应该是回收这些对象所占的堆内存空间)。缓存

二.什么样的对象会被标记成垃圾对象呢?线程

  1. 通常来讲,全部指向对象的引用都已失效,不可能再有程序能调用到这个对象,那么这个对象就成了垃圾,应该被回收。
  2. 根据这个思路,很容易就能想到用《引用计数》的办法来肯定一个对象是不是垃圾。即每当多一个引用指向对象时,引用计数加一,每当少一个引用指向对象时,引用计数减一,引用计数减到零,对象就能够被回收了。
  3. 然而引用计数有一个致命问题很差解决,就是循环引用的问题。好比说一个循环链表,他们循环引用者,引用计数永远不会为零,可是实际上程序已经不能访问他们了,他们应该被回收。(若是还没明白循环引用,第五步以后有代码说明)
  4. 因此Java其实是使用基于GC Roots的可达性分析,什么是GC Roots?全部类的静态变量,每一个线程调用栈上的本地变量(实际上咱们编程时也是要从这些地方开始访问数据),全部这些对象,以及被这些对象所指向的对象,都是活的对象。活的对象所指向的对象也是活的对象。GC经过有向图的进行可达性分析,不可达的对象就被视为是垃圾对象。
  5. 因此只要在GC的时刻,让程序暂停运行,而后从GC Roots开始分析,最后没有被标记为活对象的对象就是垃圾了。

  *代码事例解释什么是循环引用:对象

   

  如上图所示,假设咱们有两个类分别是A和B,A类中有一个字段是B类的类型,B类中有一个字段是A类类型,如今分别new一个A类对象和new一个B类对象,此时引用a指向刚new出来的A类对象,引用b指向刚new出来的B类对象,而后将两个类中的字段互相引用一下,这样即便下面进行a = null和b = null,可是A类对象仍然被B类对象中的字段引用着,尽管如今A类和B类独享都已经访问不到了,可是引用计数却都不为0.blog

三.Java中有哪几种引用生命周期

  • 强引用(StrongReference):强引用就是咱们平时使用的引用,是使用最广泛的引用。若是一个对象具备强引用,那垃圾回收器毫不会回收它(结合上面,一个对象有强引用,那么这个对象必定可达,也就是说明这个对象是活的)。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具备强引用的对象来解决内存不足的问题。(简记:永不回收)
  • 软引用(SoftReference):若是一个对象只具备软引用,则内存空间足够,垃圾回收器就不会回收它;若是内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就能够被程序使用。因此,软引用可用来实现内存敏感的高速缓存。(简记:内存不足再回收)
  • 弱引用(WeakReference):弱引用与软引用的区别在于:弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程当中,一旦发现了只具备弱引用的对象,无论当前内存空间足够与否,都会回收它的内存。不过,因为垃圾回收器是一个优先级很低的线程,所以不必定会很快发现那些只具备弱引用的对象。(简记:遇到就回收)
  • 虚引用(PhantomReference):“虚引用”顾名思义,就是形同虚设,与其余几种引用都不一样,虚引用并不会决定对象的生命周期。若是一个对象仅持有虚引用,那么它就和没有任何引用同样,在任什么时候候均可能被垃圾回收器回收。虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,若是发现它还有虚引用,就会在回收对象的内存以前,把这个虚引用加入到与之关联的引用队列中。(简记:形同虚设)

值得区分的一点是,软引用和弱引用是可选的时候和引用队列联合使用,若是与引用队列联合使用,那么当所引用的对象被垃圾回收,Java虚拟机就会把这个弱(或软)引用加入到与之关联的引用队列中。而虚引用是必须和引用队列联合使用。队列

相关文章
相关标签/搜索