理解JVM之GC&内存分配

垃圾回收机制

  • 对象存活判定算法
  • 垃圾收集算法
  • HotSpot算法实现和垃圾收集器
  • 内存分配和回收策略
    1.  对象存活判定算法(JVM回收那些对象)

概念:四种引用类型

  •  强引用:及时内存不足也不会被GC,不会随意回收强引用对象;即使抛出OOM(OutOfMemoryError),也不会随意回收强引用对象
  •  软引用:只有内存不足时,会被GC;回收后内存不足会抛出OOM异常
  •  弱引用:无论当前内存是否充足都会被GC
  •     虚引用:任何时候都会别GC

a.引用计数算法:给对象添加一个引用计数器,每当有一个地方引用他的时候就加1,当有引用失效的时候就减1;任何时刻计数器为0的对象是不能被使用的

(但是因为他不能解决相互循环引用问题,所以没有被主流JVM所使用)

b.可达性分析法:以【GC ROOT】对象作为起始点,从这个节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC ROOT没人任何引用链时,则                   这个对象是不可用的。

可以作为GC ROOT的对象

  • 虚拟机栈中引用的对象,主要是指栈帧中的本地变量
  • 本地方法栈中Native方法引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用对象

需要注意的是:在可达性分析法中被判定不可达对象未必真的就判死刑了,至少要经历两次标记过程,判断对象是否有必要执行finalize(),若判定有必要的话,还会在进行一次筛选,在finalize()中如果该对象与引用链中的任何一个对象建立关系,则它将被移除"即将回收"的集合

  2.垃圾收集算法(介绍JVM怎么回收掉这些对象)

    a.分代收集算法(是当前商业虚拟机都采用的一种算法)

  • 新生代:大批对象死去,只有少量存活。使用『复制算法』,只需复制少量存活对象即可
  •    老年代:对象存活率高。使用『标记—清理算法』或者『标记—整理算法』,只需标记较少的回收对象即可。

    b.复制算法

  • 把可用内存按容量划分为相等的两块,每次只使用其中一块。当其中一块内存用尽后,把还存活着的对象复制到另外一块内存,在将这一块内存清理掉。
  • 优点:每次都是对整个半区进行内存回收,无需考虑内存碎片等情况。只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效
  • 缺点:每次可使用的内存缩小为原来的一半,内存使用率低

有研究表明新生代中的对象98%是朝生夕死的,因此没必要按照1:1来划分内存空间,而是分为一块较大的Eden空间和两块较小的Survivor空间,

在HotSpot虚拟机中默认比例为8:1:1每次使用Eden和一块Survivor,回收时将这两块中存活着的对象一次性地复制到另外一块Survivor上,再做清理。可见只有10%的内存会被“浪费”,倘若Survivor空间不足还需要依赖其他内存(老年代)进行分配担保。




     c.标记清除法:首先标记需要被回收的对象,然后统一清除这些对象

    缺点:标记、清除效率不高;空间碎片太多,会产生大量不连续的空间碎片,可能会导致在后面需要分配较大对象时,因为无法找到连续较大的空间而提前        触发另一次GC,影响性能。

    d.标记-整理算法:首先『标记』出所有需要回收的对象,然后进行『整理』,使得存活的对象都向一端移动,最后直接清理掉端边界以外的内存

    优点:即没有浪费50%的空间,又不存在空间碎片问题,性价比较高

    一般情况下,老年代会选择标记-整理算法。

相关推荐