☆3.java虚拟机垃圾收集器与内存分配策略(上)(中阶理论篇)

1.概述

java中的垃圾回收技术被当做是java语言的伴生产物,经过半个世纪的发展,这项技术已经相当成熟,基本进入“自动化”时代,当需要排查各种内存泄漏,内存溢出问题时,当垃圾收集称为系统达到更高并发量的瓶颈时,我们就需要对这些“自动化”的技术实施必要的监控和调节。本篇主要解决一下三个问题:

  1. 哪些内存需要回收?
  2. 什么时候回收?
  3. 如何回收?

通过上一篇,java虚拟机管理的内存中,程序计数器,虚拟机栈,本地方法栈3个区域随线程而生,随线程而灭,大体上可认为在编译期可知的,因此这几个区域的内存分配和回收都具备确定性,因此不需要过多考虑回收问题,而java堆和方法区只有在程序运行过程中才知道会创建哪些对象,这部分的内存的分配和回收都是动态的,垃圾回收器所关注的就是这部分的内存,我们探讨的回收也是只这一部分。

2.对象的生死存亡

在堆里面存放着java世界中几乎所有的对象实例,垃圾收集器在堆进行回收前,第一件事就是要确定这些对象中哪些还活着,哪些已经死去,即不可能被任何途径使用的对象。

2.1引用计数算法

原理:就是给对象添加一个引用计数器,每被引用一次,计数器的值就加1,引用失效,计数器的值就减去1,这样,计数器的值为0 的对象可被认为“死去”。

优点:实现简单,判断效率高;

缺点:相互引用的两个对象,即使是这两个对象已经不可能在被访问,但是对象的计数器值不为0,例如:objA.instance = objB,objB.instance = objA.

2.2可达性分析算法

原理:通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索做过的路径被称为“引用链”,当一个对象到GC Roots没有任何引用链时,则证明对象时不可用的。

在java语言中,可以作为GC Roots的对象包括下面几种:

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

3.垃圾收集算法

本节只简单介绍几种主要算法思想。

3.1 标记-清除算法

标记-清除算法是最基础的收集算法,后面的算法都是基于这种思想进行改进的。标记-清除算法分为“标记”和“清除”两个阶段。首先是标记所有需要回收的对象,在标记完成后统一回收所有被标记的对象。

 

主要不足:①效率问题,标记和清除两个过程效率都不到;②空间问题,标记清除后会产生大量的不连续的内存碎片,空间随便太多可能会导致以后再程序运行过程中需要分配比较大的对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾回收动作。

3.2 复制算法

为了解决效率问题,一种称为“复制”的手机算法出现了,他可将内存划分为大小相等的两块,每次只使用其中一个。当着一块内存使用完了,就将或者的对象复制到另一块上面,然后再把已使用过的空间一次性清理掉。这样使得每次只对半个区域的内存进行回收,内存分配时也就不需要考虑内存碎片的复杂情况,只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效。缺点是耗费内存。

 

现在的商业虚拟机都是采用这种回收算法来收集新生代,新生代对象中的对象98%都是朝生夕死的,所以比不需要按照1:1的比例来划分内存空间,而是将内存划分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden和其中一块Survivor。当回收时,Eden和Survivor中还存活的对象一次性的复制到另外一个Survivor空间上,最后清理掉Eden和刚才使用过的Survivor空间。HotSpot虚拟机默认Eden和Survivor的大小比例是8:1。

由于我们那没办法保证每次回收都只有不多于10%的对象存货,当Survivor空间不够用时,需要依赖其他内存(这里指老年代)进行分配担保。

3.3 标记-整理算法

复制收集算法在存活对象率较高时就要进行较多的复制操作,效率将会降低。更关键的是,你如果不想浪费50%的空间,就需要额外的空间进行分配担保,以应对被使用中的内存中所有的对象都是100%存活的情况,所以子啊老年代一般不采用复制算法。

 

根据老年代的特点,使用标记-整理算法,标记过程仍然是于标记-清理算法一样,但是后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一段移动,然后直接清理掉端边界以外的内存。

3.4 分代收集算法

这是一种杂种算法,新生代采用复制算法,老年代采用标记-整理算法或者标记-清理算法。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值