我们都知道Java程序要先被编译为字节码,然后运行在JVM之上,Hbase由Java开发的,因此也是运行在JVM之上,当然对Java程序的优化都少不了JVM的优化,下面介绍JVM优化的要点和细节
垃圾回收算法
垃圾回收并不独属于Java,很早之前就已经存在,不过垃圾回收是其很重要的特性,先说垃圾回收算法
标记清除算法
该算法主要分为标记和清除两部分,先对要回收的对象进行标记,然后再进行清除。
优点:简单缺点:标记和清除的效率都不高,并且会造成空间碎片,从而导致空间浪费,提前触发Full GC
复制算法
将空间分为内存大小相等的两块,在其中的一块对象进行分配,需要进行回收的时候,将其中一块存活的对象拷贝到另外一块,然后剩下的内存块清理掉。
优点:不用考虑碎片问题,简单高效缺点:内存缩小为原本的一半,代价优点高。如果对象的存活率比较高,就要执行较多次的复制操作,效率会降低
现在新生代的一半使用复制算法,但是空间按照8:1:1进行分配,Eden和Survivor空间,最终只有10%的空间浪费掉。
标记整理算法
标记整理算法,和标记清除算法基本一样,但是整理是所有存活的对象像另外一端移动,之后清理掉边界外的内存。
分代收集算法
商业虚拟机一般采用此算法,根据对象的存活周期将内存分为几块。一般将内存分为新生代和老年代,在新生代,采用复制算法,对老年代对象存活率高,一般使用“标记整理”或者“标记清除算法”
垃圾收集器
Java中的堆内存分为新生代和老年代,针对两个不同的年代分别提供了多张不同的垃圾收集器实现。
Serial
它是最基本、发展历史最为悠久的收集器,单线程的收集器,在执行收集时,必须暂停其它的工作线程,直到它收集结束。早些年Java卡顿的现象就是由它导致的。
该回收器简单,高效,没有线程交互的开销,Serial收集器对于运行在Client模式下的虚拟机来说是一个好的选择。
ParNew收集器
它是Serial收集器的多线程版本,除了使用多条线程进行垃圾收集之外,其余行为包括Serial收集器所有的控制参数,实现上两者也共用了相当多的代码。它是运行在Server模式下的首选新生代收集器。
ParNew收集器在单线程环境中,效果不会比Serial好。在CPU的数量增加下,在GC时可以更好的利用资源。
除了Serial收集器之外,只有他可以和CMS收集器配合工作
Parallel Scavenge收集器
也是新生代收集器,也使用复制算法,又是并行的。Parallel Scanvenge收集器的特点是它的关注点是达到可控制的吞吐量(Throughout)
总运行时间= 运行用户代码时间+ 垃圾收集时间吞吐量= 运行用户代码时间/ (运行用户代码时间+ 垃圾收集时间)
停顿时间越短越适合需要与用户交互的程序,良好的响应速度能提升用户体验,而高吞吐量可以更高效的利用CPU的时间,尽快完成程序的运算任务,主要适合在后台计算而不需要太多的交互任务。
Serial Old
它是Serial收集器的老年代版本,通用是单线程,使用标记压缩算法,也是主要给client模式下的虚拟机使用。
如果用在Server模式下,则是与Parallel Scavenge收集器搭配使用。
Parallel Old
Parallel Scavenge收集器的老年代版本,使用多线程的标记-整理算法,比Serial Old收集器出现的晚,可以更充分的利用多CPU的能力。
多CPU的情况下可以使用Parallel Old
CMS收集器
CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器,注重服务的响应速度,希望系统停顿时间最短,CMS收集器非常适合这类应用的需求。
使用标记清除算法,过程有4个步骤:
• 初始标记
• 并发标记
• 重新标记
• 并发清除初始标记和重新标记,两个步骤仍需要停顿,初始标记仅仅是标记一下GC Roots能直接关联到的对象,速度很快。并发阶段就是GC Root Tracing的过程,重新标记阶段则是对用户程序继续运作而导致标记变动的一部分对象标记记录,这个阶段时间也很端比初始标记长,并发标记短。
CMS的缺点:
• 对CPU资源非常敏感,需保证足够的CPU资源
• 标记清除算法的缺点,会有大量的空间碎片
• 无法处理浮动垃圾,程序不断的运行就会有不断的垃圾产生,而CMS收集器无法集中处理它们,只好在下次GC时清理掉。
根据描述,可以看到CMS收集器适合那些服务器资源比较多人使用,内存充足,CPU充足,然后使用CMS收集器。
G1收集器
G1收集器是当今收集器技术发展的最前沿成果之一。
它的特点:
• 并行与并发,停顿时间更短
• 分代收集,仍然有分代概念
• 空间整合,不会产生碎片
• 可预测的停顿,可以设置停顿时间在多少范围内
在G1之前进行收集的范围都是整个新生代或老年代,而G1不再是这样,使用G1收集器的时候,Java堆的内存布局就与其它的收集器有很大的区别,它将整个Java堆划分为多个大小相等的独立区域,虽然还保有区域的概念,但新生代和老年代已经不再是物理隔离的了。
G1收集器过程:
• 初始标记标记GCRoots 能直接关联到的对象
• 并发标记进行可达性分析,找出存活对象,耗时稍长
• 最终标记标记并发标记期间因用户程序继续运行而导致的标记变动
• 筛选回收对各个Region区域回收价值和成本进行排序,根据用户所期望的GC停顿时间来制定回收计划。
现在JVM默认的收集器还不是G1收集器,但可以尝试。
垃圾回收器的选择
对于运行HBase相关进程的JVM垃圾回收器,不仅仅关注吞吐量,还关注停顿时间。而且停顿时间更为重要,因为HBase涉及的初衷就是解决大规模数据的实时访问问题,从这个方面CMS和G1有很大优势。
CMS作为JDK1.5已经出现的垃圾回收器,已经成熟的应用在互联网的各个行业,所以选择CMS作为老年代的回收器,与CMS搭配的有Serial和ParNEW,对比两者在多核情况下ParNew很明显有更好的性能,因此新生代采用ParNew作为垃圾收集器。
所以CMS+ParNew是很好的搭配
JVM参数
最后
这里介绍了JVM垃圾回收相关的内容。
参考
• JVM专题
注:
本文独家发布自金蝶云社区
推荐阅读
您的鼓励与嘉奖将成为创作者们前进的动力,如果觉得本文还不错,可以给予作者创作打赏哦!
请选择打赏金币数 *