垃圾收集器与内存分配策略

来源:互联网 发布:js获取当前城市名称 编辑:程序博客网 时间:2024/06/06 22:22

         当进行GC时,我们需要考虑如下几件事情:(1)哪些内存需要回收;(2)什么时候回收;(3)如何回收;

一.对象已死吗?

  1.引用计数法:给对象中添加一个引用计数器,每当一个地方引用它时,计数器值就加1,当引用失效时,计数器值就减一,任何时刻计数器为0的对象就是不可再用的。

   缺点:很难解决对象之间相互循环引用的问题。Java虚拟机里并没用这种放方法来管理内存。

  2.可达性分析算法:通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots 没有任何引用链相连时,则证明此对象时不可用的。

  可作为GC Roots的对象包括:

  1. 虚拟机栈(栈帧中的本地变量表)中引用的对象;
  2. 方法区中类静态属性引用的对象;
  3. 方法区中常量引用的对象;
  4. 本地方法栈中JNI(即一般说的Native)方法引用的对象;

  3.引用类型:强引用、软引用、弱引用、虚引用。

二.垃圾收集算法

  • 标记-清除算法:首先标记处所有需要回收的对象,在标记完成后统一回收所有被标记的对象。

    缺点:

      效率问题:标记和清除两个过程的效率不高;

      空间问题:标记清除之后会产生大量不连续的碎片,分配较大对象无法找到做够内存而提前出发GC;

  • 复制算法:将可用内存按容量划分为大小相等的两块,每次只使用其中一块,当一块用完了,就将还存活的对象复制到另一块上面,解决了效率问题,但是将内存缩小了一半,代价太大。
  • 标记-整理算法:不是直接对可回收对象进行清理,而是让所有存活对象都像一端移动,然后直接清理端边界以外的内存。
  • 分带收集算法:划分新生代和老年代。

三.垃圾收集器

 并行:指多条垃圾收集线程并行工作,单此时用户线程任然处于等待状态;

 并发:指用户线程与垃圾收集线程同时执行(但不一定是并行的,可能会交替执行),用户程序在继续运行,而垃圾收集程序运行于另一个CPU上。

  • Serial收集器:单线程收集器,在进行垃圾收集时,必须暂停其它所有的工作线程,知道它收集完成。新生代收集的选择。
  • ParNew收集器:多线程收集器,新生代收集的选择。
  • Parallel Scavenge收集器:新生代收集器,复制算法的收集器,并行的多线程收集器,达到一个可控制的吞吐量;
  • Serial Old收集器;
  • Parallel Old收集器;
  • CMS收集器:获取最短回收停顿时间为目标的收集器;
  • G1收集器:并行与并发;分带收集;空间整合;可预测的停顿;

四.内存分配与回收策略

  对象的内存分配,往大方向讲,就是在堆上分配,(但也可能经过JIT编译后被拆散为标量类型并间接地栈上分配),对象主要分配在新生代的Eden区上,如果启动了本地线程分配缓冲,将按线程优先在TLAB上分配,少数情况下也可能会直接分配在老年代中。

  • 对象优先在Eden分配;
  • 大对象直接进入老年代;
  • 长期存活的对象将进入老年代;
  • 动态对象年龄判定;
  • 空间分配担保;




原创粉丝点击