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

2019-06-26  本文已影响0人  cjxll
如何判断对象是否存活?
  1. 引用计数法
    给对象添加一个引用计数器,每当一个地方引用它时,计数器值就加1;
    当引用失效时,计数器值就减1,任何时刻计数器为0的对象就是不可能再被使用的。
    很难解决对象间相互循环引用的问题
  2. 可达性分析算法
    通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路称为引用链(reference chain)。当一个对象到GC Roots没有任何引用链相连时,则该对象不可用。
    可作为GC Roots的对象包括下面几种

引用类型

生成还是死亡

如果对象在进行可达性分析后发现没有与GC Roots相连接的引用链,那它将会被第一次标记并且进行一次筛选,筛选条件是该对象是否有必要执行finalize()方法。当对象没有覆盖finalize()方法或者,finalize()已经被虚拟机调用过,虚拟机将这2种情况视为“没有不要执行”。
如果该对象被判定为有必要执行,那么这个对象就会被放置在一个F-Queue的队列中,并由一个Finalizer线程去执行它

回收方法区

永久代的垃圾收集主要回收两部分:废弃常量和无用类
判定无用类的条件:

垃圾收集算法

  1. 标记-清除算法
    标记所有需要回收的对象,标记完成后统一回收所有被标记的对象,效率不高,容易造成内存碎片
  2. 复制算法
    将内存按容量划分为大小相等的2块,每次使用1块,当这块内存用完就将存活的对象复制到另一块。缺点可用内存缩小一半。
  3. 标记-整理算法
    标记过程一样,让所有存活的对象移动到一段,然后直接清理掉其他内存
  4. 分代收集算法
    年轻代:对象存活周期短,采用复制算法
    老年代:对象存活率高,采用标记法
枚举根节点

GC停顿(Stop the world):可达性分析工作必须执行在能确保一致性的快照执行中,一致性指整个分析期间整个执行系统看起来就像被冻结在某个时间点上,不可以出现分析过程中对象引用关系发生变化的情况。导致GC进行时必须停止所有JAVA线程
Hotspot中使用一组称为OopMap的数据结构来达到这个目的,在类加载的时候,会记录下来

安全点

hotspot没有为每条指令都生成OopMap,只是在特定的位置记录了这些信息,这些位置称为安全点,程序到达安全点时才能暂停,
安全点的选择标准:是否具有让程序长时间执行的特征,例如方法调用,循环跳转,异常跳转等。
主动式中断:当GC需要中断线程时,不直接对线程操作,仅仅设置一个标志,各线程执行时主动去轮询这个标志,发现中断标志为真时,就自己中断挂起

安全区域

安全区域指一段代码片段之中,已用关系不会发生改变。在这个区域任意地方开始GC都是安全的。
在线程执行到safe region中的代码时,首先标志自己已经进入了sage region,在这段时间里JVM要执行GC时,就不用管标志自己为sage region的状态的线程,在线程要离开safe region时,它要检查GC过程,如果完成了就继续执行,否则它必须等到收到可以安全离开的信号为止。

垃圾收集器

  1. 新生代收集器:
  1. 老年代收集器

内存分配与回收策略

  1. 对象优先分配在Eden区,当Eden区没有足够空间时,JVM发起一次Minor GC.
  2. 大对象直接进入老年代,避免Eden区以及2个Survivor区之间发生大量的内存复制
  3. 长期存活的对象将进入老年代,经过多次Minor GC(默认15次)后仍然存活,将会被晋升到老年代
  4. 动态对象年龄判断,如果在Survivor空间中相同年龄所有对象大小的总和大于Surivivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无需等到MaxTenuringThreshold中要求的年龄
  5. 空间分配担保,在Minor GC之前,虚拟机先检查老年代最大可用连续空间是否大于新生代所有对象总空间,如果成立,那么Minor GC可以确保是安全的,如果不成立,则检查是否允许担保失败,若果允许,那么继续检查老年代最大可用内存空间是否大于历次晋升到老年代对象的平均大小,如果大于,将尝试进行一次Minor GC,否则进行Full GC
上一篇 下一篇

猜你喜欢

热点阅读