您的位置:首页 > 其它

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

2017-12-28 15:26 260 查看

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

HotSpot的算法实现

枚举根节点(寻找GC ROOT)

由于目前大多数JVM垃圾回收判断机制都是采用的可达性分析,那么在JVM需要发生GC的时候,就需要寻找执行方法中的根节点(GC ROOT);如果说就目前程序一直在不停的执行,那么对于根节点(GC ROOT)是有可能在不停的变化的;我们这里需要JVM停止当前所有程序的执行(stop the world),才能进行根节点的可达性分析;但是就目前常见的Java方法可能极大,所以HotSpot提出一个OopMap的数据结构来存储目前方法内的对象地址和偏移量(可以直接理解为GC ROOT的位置)

安全点

对于一段执行的方法来说,如果需要在每一行记录OopMap那么JVM的空间成本就会提高,事实上HotSpot也并没有给每一条指令生成OopMap;只是在“特定的位置”上生成OopMap,这些特定位置我们称之为安全点

安全点生成标准

对于普通的指令来说,执行速度是非常快的,一般来说安全点都在“长时间执行”的指令处生成,例如方法调用,循环跳转和异常跳转等

执行到安全点的方式

因为安全点不是在每一条指令上生成,那么一旦垃圾收集器需要回收内存的时候,那么需要让每一个线程执行到安全点的位置(因为有可能部分线程现执行位置不在安全点),执行方式如下

抢占式中断

在GC发生时,JVM会首先停掉所有线程,当发现某一线程不在安全点,恢复线程执行状态,直到所有线程都在安全点上,这样称之为抢占式中断;但是绝大多数JVM都没有采用

主动式中断

在GC发生时,JVM不会直接对所有线程直接操作,而是设置一个标识,所有线程在执行到安全点的时候都会主动去轮询这个标识,一旦标识为真,那么线程自动挂起直到GC完成,设置标识为假的时候继续执行;这样称之为主动式中断

安全域

安全域是对安全点的一个补充或者是一种拓展;安全域指的是在一段特定的区域所有垃圾收集器在进行根节点的可达性分析都是可行的;之所以要加入安全域是因为线程可能出现等待或者休眠的状态,那么GC不可能去等待休眠的线程执行到安全点,所有拓展了安全域的概念

垃圾收集器



上图主要显示两个区域(Young generation:新生代;Tenured generation: 老年代)使用不同的收集器;中间的连线说明它们直接可以搭配使用

Serial收集器

概念

从名称我们可以看出来,Serial是一个单线程收集器;所谓单线程收集器意思就是Java虚拟机发生GC的时候,需要停止所有线程的执行,然后Serial单线程进行GC直到完成

使用算法

使用复制算法收集新生代内存

搭配老年代收集器

CMS(Concurrent Mark Sweep):同步标记-清除收集器

Serial Old:老年代单线程收集器

优缺点

优点:避免线程之间通信消耗成本;简单高效适合客户端(client)模式运行的JVM

缺点:需要收集的新生代内存大时,暂停(Stop the world)时间长,无法忍受

Serial和Serial Old运行示意图



ParNew收集器

概念

ParNew实际上是Serial的多线程实现,就是在GC发生时是多个线程==并行==收集内存

参数设置(与Serial实现一样)

-XX:PretenureSizeThreshold:设置至今进入老年代的对象大小

-XX:SurvivorRatio:设置新生代中Eden和Survivor比例大小;默认是8

-XX:HandlePromotionFailure:是否一下分配担保失败;1.5默认关闭;1.6某人开启

-XX:+UseConcMarkSweepGC:设置老年代GC使用CMS,默认新生代收集器是ParNew

-XX:UseParNewGC:强制新生代使用ParNew作为垃圾收集器

-XX:ParallelGCThreads:设置ParNew收集线程数;少于或者等于8个CPU时,默认值为CPU值;CPU数量大于8时,默认值比CPU值少

使用算法

和Serial一样同样也是使用复制算法

搭配老年代收集器

Serial Old:老年代单线程收集器

CMS(Concurrent Mark Sweep):同步标记-清除收集器

优缺点

优点:随着CPU数量的增多,ParNew相比于Serial可以更好的利用CPU;效率更好

缺点:CPU数量为1时,ParNew在线程之间切换上下文耗费资源导致效率肯定不如Serial;当然在CPU数量为2时;ParNew也不敢百分百保证超过Serial收集器

并行和并发区别

并行(Parallel):是指多个线程同时收集内存,但是对于用户线程依然是停止的

并发(Concurrent):是指用户线程和GC线程同时进行中(当然对于GC线程也可以是多个并行的),用户线程依然进行着;而GC线程收集线程也进行着
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  jvm 内存分配 算法