昨天咱们用比较精简的文字讲了 Java 虚拟机结构,没看过的能够直接从这里查看:
每日一问:你了解 Java 虚拟机结构么?java
今天咱们必须来看看 Java 虚拟机的垃圾回收算法是怎样的。不过在开始以前,咱们必定得肯定哪些是活着的对象,又有哪些是能够进行回收的。算法
对应判断一个对象是否能够回收,我想引用计数必定是最容易被想到的算法了吧。给每一个对象加一个引用计数器,每当有一个地方引用它时,计数器就加 1,引用失效后减 1,当对象的计数器为 0,则说明这个对象能够被回收了。这个算法很是简单,但存在一个很是大的弊端:一旦两个对象相互引用,这个算法就没辙了。缓存
Java 就是采用的根搜索算法进行判断对象是否存活。这个算法的思路是:经过一系列名为 "GC Roots" 的对象做为起始点,从这些结点开始向下搜索,当一个对象到 "GC Roots" 没有任何引用链相连的话,则证实这个对象是能够被回收的。在 Java 中,能够做为 "GC Roots" 的对象包括:网络
在 JDK 1.2 以后,引用被分为了强引用、软引用、弱引用和虚引用四种,这四种引用强度依次逐渐减弱。学习
强引用在 Android 代码中广泛存在,只要强引用还在,垃圾回收器就不会回收掉被引用的对象,这就是为何咱们用内部类持有 Activity 实例会形成内存泄漏的根本缘由。code
软引用用来描述一些还有用,但非必需的对象,用 SoftReference
实现,被软引用关联的对象,在系统将要发生 OOM 以前,会把这些对象列进回收范围之中并进行第二次回收。软引用在 Android 中主要是用于作缓存,好比软引用缓存网络请求的图片。对象
弱引用也是用来描述非必需对象的,但它的强度比软引用更弱,用 WeakReference
实现。被弱引用管理的对象只能生存到下一次垃圾收集发生以前。弱引用在 Android 中主要用于处理内存泄漏。生命周期
虚引用其实没啥好说的,一个对象是否有虚引用的存在,彻底不会对生存时间构成影响,也没法经过虚引用来取得一个对象实例。就目前为止,我尚未在 Android 开发中使用过它。图片
学习 Java 虚拟机的垃圾回收算法以前,咱们必须来看看咱们常见的几种垃圾回收算法的思想,并把它们的优劣进行必定的对比,这样必定才能让你理解更加深入。内存
标记 - 清除算法应该是最简单基础的收集算法了,只须要标记须要回收的对象,标记完成后统一回收便可。但其有两个很是明显的弊端。
复制算法主要是将可用内存划分为大小相等的两块,每次只使用其中的一块,当这一块内存用完,就将存活着的对象复制到另外一块内存上去,而后把已使用过的内存空间一次性清理掉。复制回收算法能有效地避免内存碎片,可是算法须要把内存一分为二,致使内存使用率大大下降。
复制收集算法在对象存活率较高时就须要进行较多的复制操做,效率非很低。 效率会很低。标记-整理算法就解决了这样的问题,一样采用的是根搜索算法进行存活对象标记,但后续是将全部存活的对象都移动到内存的一端,而后清理掉端外界的对象。
当前包括 Java 虚拟机在内的商业虚拟机都采用的是分代收集算法。这种算法其实就是根据对象的存活周期不一样将内存划分为几块。通常把 Java 堆分为新生代和老年代,而后根据各个年代的特色采用最适合的收集算法。
前面说了 Java 虚拟机采用的是分代回收算法,该算法会根据各个年代的特色采用最适合的收集算法,咱们就必须了解 Java 堆分的各个年代区域的特色。
JVM 中共分为三个代:新生代、老年代和持久代。其中持久代主要存放的是 Java 类的类信息,与垃圾收集要收集的 Java 对象关系不大。
Java 垃圾回收包含两种类型:Scavenge GC 和 Full GC。
System.gc()
被显式调用;好了,这一篇文字比起前面的文字稍微多了一些,主要是知识关联性稍微大了一些,又不适合分开讲解,因此就只能这样了。