jvmjvm性能调优

jvm垃圾回收器&基本参数

2019-10-02  本文已影响0人  javap

祝大家国庆佳节快乐!
接上一篇文章,为大家介绍介绍了jvm垃圾回收器的回收策略以及gc算法,这篇为大家介绍jvm中的gc垃圾回收器以及常用的jvm调优配置参数!

jvm垃圾回收器

在jvm中截止半月前发行的jdk13,jvm的内置gc也只到了G1。在jvm的gc主要分为两大类;这个可以从不同的角度进行分析,可以从同步回收还是异步回收,也可以从新生代和老年代进行划分!

简单的jvm配置参数

jvm配置参数

次处注意,在jdk1.8之后,所谓的永久代也就是配置参数为-XX:PermSize以及-XX:MaxPermSize这两个将不再使用,因为jvm优化策略将原来归为jvm内存的方法区也就是永久代划分出jvm内存,将直接使用机器的内存更名为元数据空间,配置参数:-XX:MetaspaceSize以及-XX:MaxMetaspaceSize两个!

选用不同的gc回收器的jvm参数配置

+XX:Use[垃圾回收器name]GC

Serial垃圾回收器

这个回收器在新生代是同步的回收策略,gc算法采用的是标记复制算法,老年代采用的也是同步的回收机制,gc算法是标记整理算法(次处,大家不要疑惑,为什么所有的老年代垃圾回收器都是采用标记整理算法或者标记清楚算法呢?为何不采用标记复制算法呢?大家这样想象一下,在old的老年代中,也就是我们常常配置的-Xms,-Xmx这两个参数值是规定jvmHeap的空间大小的因此Old区域的内存大小也就是(HeapSize-(Eden+s0+s1))在此,如果old区域也采用标记复制算法的话,那么岂不是老年代只有一半的内存空间能够使用,这样的话性能以及效率问题就会大大的减少!之余那为什么新生代有的gc回收器采用标记复制的算法只因为,在上一篇文章也说过,一半gc在回收内存的时候,会把所有的用户线程全部停止,执行gc回收,也就是STW,STW在进行Full GC 的时候会消耗的事件比较长,因此新生代的gc回收器一般采用标记复制算法,这样能够使对象尽可能的新生代发生MinorGC从而回收掉对象,尽可能少的发生full gc这样会大大的减少你的系统的停顿事件,从而内存也能有较好的生存周期)。


Serial垃圾回收器.png
ParNew收集器

有了上述的在新生代串行的也就是同步的垃圾回收器之后,当然串行的效率往往不如并行的,因此jvm产出了一种在新生代有用并行垃圾回收的ParNew回收器。
此回收器在新生代采用并行垃圾回收策略,gc算法为标记复制算法,老年代还是采用传统的串行,gc算法也是标记整理算法!


ParNew收集器.png
ParallelScavenge回收器

此回收器和上面的ParNew回收器在新生代以及老年代所有的策略基本上是一致的,但是在一些细节的方面做了不少的优化操作,增加了一些能够提升容错率的配置参数:
-XX:MaxGCPauseMillis --控制垃圾回收时最大的停顿时间(单位ms)
-XX:GCTimeRatio --控制程序运行的吞吐量大小
吞吐量大小=代码执行时间/(代码执行时间+gc回收的时间)
-XX:UseAdaptiveSizePolicy --内存调优交给虚拟机管理(没用过,有兴趣的同学自行测试)
此垃圾回收器,利用时要多对自己的程序进行监控分析,不要因为想提高吞吐量,减少gc回收的时间,导致程序捡了芝麻丢了西瓜!


Parallel Scavenge回收器.png
Serial Old回收器

这个回收器在上述已经阐述过了,PPT截图我已经为大家尽可能的划分清楚,请自行看图分析理解,在此不过多阐述!


Serial Old回收器.png
Parellal Old回收器

Parellal Old回收器是Parellal Scavenge的老年代版本,大家看图自行理解分析,此垃圾回收器基本不适用于web程序,因为Old老年代的标记整理算法有大量的STW存在,因此会造成web程序的相应迟钝,甚至暂停。多实用与桌面的cs架构程序回收内存。


Parellal Old回收器.png
Coucurrent Mark Sweep回收器(即CMS)

程序员口中娓娓道来的CMS也就是次处的垃圾回收器,这个垃圾回收器可谓说是在jdk的发展史上一次重大的突破,在web应用中起到至关重要的作用。
此垃圾回收器的gc算法不是传统的一些标记整理或者说是标记复制等,而是采用“可达性分析的策略”。

可达性分析
可达性分析算法.png

G1和CMS的回收机制基本完全一致,在此把CMS阐述的清楚一些,后续的G1则不进行过多的分析!
可达性分析有点类似树形的结构,也就是说在程序调用中,一个用户线程进入Servlet要执行业务,比如一个添加任务,那么后台就会采用,第一:入缓存,第二:入库。那么这样一个场景就类似于一个树枝的分差,后续可能还会进行更多的分叉。
在此之上,我们假设CMS在内部有三种标记颜色,黑色,灰色,和白色,
黑色标记对象的Roots节点,灰色标记下面的子节点,白色为不用的对象节点。
那么首先:在进行gc回收内存之前就会进行可达性分析,用到的对象标记为黑色Roots节点。
第二步:标记roots下的子节点,将子节点作为根节点继续标记,也就是将第一步中标记为灰色的子节点作为根节点Roots再进行下一的标记操作。
第三步:等标记阶段执行完毕之后,进行清除算法,紧接着最后再对内存进行一次整理操作!(在此,可能有人会问,内存都清理了,为什么还要整理一次内存,那么上一篇文章中我说的标记清楚算法,你再去看一下,在标记清楚算法中,清楚完毕之后,会存在一些内存片段的问题,这样后制造出内存泄漏的问题,如果不对内存进行整理,那么最终会酿造出OOM)
此处的第三阶段并发清除阶段gc不会终止用户线程的,因此这也是CMS的优点之处所在!


Concurrent Mark Sweep回收器.png

针对图中阶段进行解析:
初始标记:就是第一步的阶段,标记Roots节点
重新标记:就是可达性分析的核心思想。(次处所有的用户线程都将停止,因为,假设,你在逛商场的时候,边吃瓜子边走路,保洁阿姨跟在你后面打扫,你觉得可能吗?gc也是这样的一个道理,我在清楚垃圾的时候,是不允许用户线程再给我制造垃圾的。)
并发清理:次数就能彻底体现出CMS垃圾回收器的优点,在清除垃圾的时候,不会打扰到用户线程的进行,因此你的web程序也就不会刻意的停顿!

G1回收器

G1回收器是jdk9之后默认的垃圾回收器,它的回收策略得到了一次颠覆,但是清楚的算法和CMS大致都是相同的。但是在对于jvm heap内存结构做了一次颠覆,原来jvm的heap内存结构是Eden+survivor0+survivor1+Old的,但是G1把所有的heap内存空间全部划分为若干个块,用不同的标记去做。如图所示,回收策略和算法和CMS一样,请自行理解学习!


G1回收器.png

垃圾回收器的合理使用

上述已经和大家介绍完了jdk内部的所有的gc以及特点和gc的算法。那么具体该怎么去搭配应用呢?
在此我为大家用PPT做了一张结合图供大家理解应用!


gc结合使用图解.png

图中的横线划分出了jvm的heap结构的图,横线上面为年轻代,下面则为老年代,gc直接的连线则表示两者能够相互的结合使用。在图中G1比较特殊。它可以在老年代和新生代中同时使用!
虽然为大家介绍了jvm中所有的gc以及其的优缺点,可能大家都会觉得现在的G1最牛X,其实不然,关于gc的选择甚至你公司有关jvm的调优方面的工作是需要结合你公司的项目长期的进行监控和测试而决定的,而不是直接选用最好的gc回收器,如果盲目选择,到最后,可能带来就是事半功倍!
后续有时间,会为大家介绍jvm的内存分配和回收策略,欢迎一起学习讨论!

上一篇下一篇

猜你喜欢

热点阅读