码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2016-05-28 17:40:04      阅读:230      评论:0      收藏:0      [点我收藏+]

标签:

  Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的“高墙”,墙外面的人想进去,墙里面的想出来。

一、判断对象是否已经死了

  1.应用计数算法

  给每个对象添加一个引用计数器,每当有一个地方引用它时,计数器的值就加1,当应用失效的时候就减1,任何时刻计数器为0的时候表示对象就是不可用状态。

  但是Java虚拟机并没有选择这种算法,原因是很难解决对象之间相互引用的问题。

  2.可达性分析算法

  通过一系列的称为“GC Root”的对象作为起点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Root没有任何引用链相连接的时候,证明这个对象是不可用的。

  技术分享

  在Java语言中,作为GC Root的对象有如下

  ①虚拟机栈中引用的对象。

  ②方法区中类静态属性引用的对象。

  ③方法区中常量引用的对象。

  ④本地方法栈中JNI(Native方法)应用的对象。

 

二、垃圾收集算法

  1.标记—清除算法

  “标记”:首先标记出所有需要回收的对象。

  “清除”:标记完成后统一回收被标记的对象。

  不足之处:① 效率问题,标记和清理两个过程效率都不高。②标记清理之后会产生大量不连续的内存碎片。

  2.复制算法

  将内存分成两个大小相等的两块,每次只使用一块,当这一块内存用完了,就将还存活的对象复制到另一块上,然后把已经使用过的内存空间一次清理掉。

  好处:回收是一次性回收,也不用考虑内存碎片等复杂情况。只需要移动堆顶的指针,实现简单,效率高。

  坏处:浪费一般内存。

  现在商业虚拟机使用的这种算法回收新生代:将内存分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden和其中一块Survivor。当回收的时候,将Eden区和Survivor区中还存活的对象一次性的复制到另一块survivor空间上,最后清理Eden区和刚才使用的survivor区。HotSpot默认Eden与Survivor比例是8:1.,所以只有10%空间浪费。当Survivor空间不够用时,需要依赖其他内存(老年代)进行分配担当

  3.标记—整理算法

  复制算法在对象存活率比较高的时候会进行比较多的复制操作,效率会变低,所以老年代不适合这种算法。

  技术分享

 

  4.分带收集算法

  根据对象活跃周期不同将内存划分为几块:一般把Java堆分为新生代和老生代。

  新生代:一般使用复制算法。

  老生代:一般使用“标记—清理算法”或者“标记—整理算法”。

 

三、HotSpot的算法实现

  1. 枚举根节点

  当进行垃圾回收前的对象可达性分析时,对执行时间的敏感体现在GC停顿上。因为这项分析工作必须在一个能保证一致性的快照中进行——整个分析过程中所有执行都停在某个时间点上。GC停顿是性能瓶颈的重要原因。

  使用OoMap实现快速节点枚举。

  2.安全点(Safepoint)

  并不是每个指令都会创建OoMap,我们会为特定的指令或者说程序特定的位置创建OoMap,例如:方法调用、循环跳转、异常跳转等。

  如何将所有线程都跑到安全点停顿:①抢先式中断,在GC发生时,首先把所有线程全部中断,如果发现不在安全点上则恢复线程叫它跑到安全点再停止。

  3.安全区域

  安全区域表示一段代码,不会引起引用变化。

 

四、垃圾收集器

        技术分享

  

 

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

标签:

原文地址:http://www.cnblogs.com/zhangzongxing01/p/5537856.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!