深入拆解Tomcat & Jetty
李号双
eBay技术主管
立即订阅
6067 人已学习
课程目录
已完结 44 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | Java程序员如何快速成长?
免费
模块一 必备基础 (4讲)
01 | Web容器学习路径
02 | HTTP协议必知必会
03 | 你应该知道的Servlet规范和Servlet容器
04 | 实战:纯手工打造和运行一个Servlet
模块二 整体架构 (9讲)
05 | Tomcat系统架构(上): 连接器是如何设计的?
06 | Tomcat系统架构(下):聊聊多层容器的设计
07 | Tomcat如何实现一键式启停?
08 | Tomcat的“高层们”都负责做什么?
09 | 比较:Jetty架构特点之Connector组件
10 | 比较:Jetty架构特点之Handler组件
11 | 总结:从Tomcat和Jetty中提炼组件化设计规范
12 | 实战:优化并提高Tomcat启动速度
13 | 热点问题答疑(1):如何学习源码?
模块三 连接器 (9讲)
14 | NioEndpoint组件:Tomcat如何实现非阻塞I/O?
15 | Nio2Endpoint组件:Tomcat如何实现异步I/O?
16 | AprEndpoint组件:Tomcat APR提高I/O性能的秘密
17 | Executor组件:Tomcat如何扩展Java线程池?
18 | 新特性:Tomcat如何支持WebSocket?
19 | 比较:Jetty的线程策略EatWhatYouKill
20 | 总结:Tomcat和Jetty中的对象池技术
21 | 总结:Tomcat和Jetty的高性能、高并发之道
22 | 热点问题答疑(2):内核如何阻塞与唤醒进程?
模块四 容器 (8讲)
23 | Host容器:Tomcat如何实现热部署和热加载?
24 | Context容器(上):Tomcat如何打破双亲委托机制?
25 | Context容器(中):Tomcat如何隔离Web应用?
26 | Context容器(下):Tomcat如何实现Servlet规范?
27 | 新特性:Tomcat如何支持异步Servlet?
28 | 新特性:Spring Boot如何使用内嵌式的Tomcat和Jetty?
29 | 比较:Jetty如何实现具有上下文信息的责任链?
30 | 热点问题答疑(3):Spring框架中的设计模式
模块五 通用组件 (4讲)
31 | Logger组件:Tomcat的日志框架及实战
32 | Manager组件:Tomcat的Session管理机制解析
33 | Cluster组件:Tomcat的集群通信原理
特别放送 | 如何持续保持对学习的兴趣?
模块六 性能优化 (8讲)
34 | JVM GC原理及调优的基本思路
35 | 如何监控Tomcat的性能?
36 | Tomcat I/O和线程池的并发调优
37 | Tomcat内存溢出的原因分析及调优
38 | Tomcat拒绝连接原因分析及网络优化
39 | Tomcat进程占用CPU过高怎么办?
40 | 谈谈Jetty性能调优的思路
41 | 热点问题答疑(4): Tomcat和Jetty有哪些不同?
结束语 (1讲)
结束语 | 静下心来,品味经典
深入拆解Tomcat & Jetty
登录|注册

34 | JVM GC原理及调优的基本思路

李号双 2019-07-30
和 Web 应用程序一样,Tomcat 作为一个 Java 程序也跑在 JVM 中,因此如果我们要对 Tomcat 进行调优,需要先了解 JVM 调优的原理。而对于 JVM 调优来说,主要是 JVM 垃圾收集的优化,一般来说是因为有问题才需要优化,所以对于 JVM GC 来说,如果你观察到 Tomcat 进程的 CPU 使用率比较高,并且在 GC 日志中发现 GC 次数比较频繁、GC 停顿时间长,这表明你需要对 GC 进行优化了。
在对 GC 调优的过程中,我们不仅需要知道 GC 的原理,更重要的是要熟练使用各种监控和分析工具,具备 GC 调优的实战能力。CMS 和 G1 是时下使用率比较高的两款垃圾收集器,从 Java 9 开始,采用 G1 作为默认垃圾收集器,而 G1 的目标也是逐步取代 CMS。所以今天我们先来简单回顾一下两种垃圾收集器 CMS 和 G1 的区别,接着通过一个例子帮你提高 GC 调优的实战能力。

CMS vs G1

CMS 收集器将 Java 堆分为年轻代(Young)或年老代(Old)。这主要是因为有研究表明,超过 90%的对象在第一次 GC 时就被回收掉,但是少数对象往往会存活较长的时间。
CMS 还将年轻代内存空间分为幸存者空间(Survivor)和伊甸园空间(Eden)。新的对象始终在 Eden 空间上创建。一旦一个对象在一次垃圾收集后还幸存,就会被移动到幸存者空间。当一个对象在多次垃圾收集之后还存活时,它会移动到年老代。这样做的目的是在年轻代和年老代采用不同的收集算法,以达到较高的收集效率,比如在年轻代采用复制 - 整理算法,在年老代采用标记 - 清理算法。因此 CMS 将 Java 堆分成如下区域:
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《深入拆解Tomcat & Jetty 》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(19)

  • -W.LI-
    年轻代设置过大:
    1.生命周期长的对象会长时间停留在年轻代,在S0和S1来回复制,增加复制开销。
    2.年轻代太大会增加YGC每次停顿的时间,不过通过根节点遍历,OopMap,old scan等优化手段这一部分的开销其实比较少。
    3.浪费内存。内存也是钱啊虽然现在租的很便宜
    老年代设置过大:
    1.降低FGC频率,有些堆外内存比如直接内存,需要靠FGC辅佐回收的,就会无法释放。万一剩余的堆外内存不够程序也会宕机的吧
    2.单次FGC时间变长,如果在夜深人静的时候主动触发FGC内啥影响,如果白天业务繁忙的时候就凉凉
    3.增加YGC的时间,old scan阶段会扫描老年代,而且这个阶段耗时在YGC总比重很大。

    最好别让太多老年代对象引用年轻代对象,这个坑很痛。
    2019-07-30
    14
  • -W.LI-
    李老师好!感觉老师今天偷懒了,CMS负责老年代回收,年轻代一般配合parNew使用。
    大概啥情况下使用G1比较好啊?之前看见网上说,大堆多核,jdk9以及以上可以使用G1,jdk8的话除非cms满足不了需求不然不建议使用G1。
    G1不太了解老师能推荐下资料么?
    我觉得工具,可以提高效率,初学者优先搞清楚原理扎实基础比较好。

    作者回复: g1实现很复杂,有人专门写了本书来讲,原理入门可以看看这篇文章:https://yq.aliyun.com/articles/444436

    2019-07-30
    1
    7
  • 新世界
    设置过大,回收频率会降低,导致单次回收时间过长,因为需要回收的对象更多,导致GC stop the world时间过长,卡顿明显,导致请求无法及时处理

    作者回复: 对的,主要是会引起gc停顿时间过长

    2019-07-30
    2
    4
  • 业余草
    需要实际操作一遍,光看是记不住的,过一段时间就忘记了。
    2019-07-30
    3
  • QQ怪
    设置过大回收频率降低,单次回收的对象量大,回收stw时间过长,设置大也不好,过小也不好,设置适合的才是最好的
    2019-07-30
    2
  • 小唐
    老师可以把code分享到github吗?我想自己执行一遍加深印象,这样我们就不用自己配置了,多谢老师!
    2019-08-13
    1
  • nightmare
    分情况,如果是G1大年轻代和大老年代没什么问题 如果是cms parnew的话 也需要看情况 如果你的并发比较大并且很快占满eden区 或者 用jstat监控 supervisor区占比一直高于百分之70这个时候 这个时候加大新生代就没有什么问题 如果要很久才占满eden区 或者supervisor区占比比较小 这个时候就要把 新生代 设置小一点 减少新生代回收时间 老年代也要看年轻代晋升到老年代平均占多大 如果晋升很快并且对象占比较大 大一点没问题 否则就需要减少老年代
    2019-07-30
    1
  • 靠人品去赢
    之前觉得用到JDK8就够了,据说是XXX维护的最后一个版本。老师讲完G1收集器,突然有兴趣,怪不得人家IDEA新的直接自带JDK11,技术越新越有惊喜啊。
    2019-11-28
  • Geek_8c4282
    老师,我不太明白,为什么你调大堆内存后堆的大小会频繁震荡,没有发生minorgc和fullgc为什么堆的大小会上下变化,请老师告知下,谢谢
    2019-11-15
  • Geek_ebda96
    老师您好,请问对于新生代的内存,supervisor和eden区域,大小比例怎样设置合理,这个比例是否对GC性能有影响呢?
    2019-08-03
  • CN8818

    执行命令:java -Xmx2048m -Xss256k -verbosegc -Xlog:gc*,gc+ref=debug,gc+heap=debug,gc+age=trace:file=gc-%p-%t.log:tags,uptime,time,level:filecount=2,filesize=100m -jar target/demo-0.0.1-SNAPSHOT.jar
    java -Xmx2048m -Xss256k -verbosegc -Xlog:gc*,gc+ref=debug,gc+heap=debug,gc+age=trace:file=gc-%p-%t.log:tags,uptime,time,level:filecount=2,filesize=100m -jar target/demo-0.0.1-SNAPSHOT.jar
    报错:
    Unrecognized option: -Xlog:gc*,gc+ref=debug,gc+heap=debug,gc+age=trace:file=gc-%p-%t.log:tags,uptime,time,level:filecount=2,filesize=100m

    作者回复: 要采用最新jvm版本12

    2019-08-01
  • 月如钩
    实操很重要呀,朋友们,纸上谈兵很容易忘
    2019-08-01
  • xj_zh
    老师,可以讲一讲undertow吗,为什么spring boot 2.0 选择undertow做为默认WEB容器。
    2019-07-31
  • 双月鸟
    CMS默认开启-XX:+UseAdaptiveSizePolicy,所以G1收集器会根据算法动态决定年轻和年老代的大小不能成为G1的优势
    2019-07-30
    1
  • 谢谢老师。
    2019-07-30
  • 许童童
    老师讲得好啊,虽然工作中没有用到Java,但读了这篇文章也基本懂了!
    2019-07-30
  • 对于CMS来说,设置很大的堆内存,在导致单次STW时间长,会导致服务不可用,定时器出问题?对响应敏感的系统来说不太友好,但堆内存设置太小又会导致频道GC,所以需要综合评估。那么如何使用超大机器内存呢?可以使用集群方式部署,单个应用设置较小的堆内存。
    对于G1来说,文中有提到可以设置较大内存,因为G1是局部收集,但极端情况下,区域之间的对象引用关系非常多,也会导致大面积回收,STW时间会较长。
    目前Java8使用CMS的较多,那么G1普及可能还需要时间吗?

    作者回复: 随着java9 普及开,就默认用g1了

    2019-07-30
    2
  • 老师,我想问个问题:在docker中运行的springboot(使用默认的tomcat容器),如何查看tomcat的gc日志?

    作者回复: 可以登到容器内去看,不过一般会把容器的日志目录mount到主机的某个目录

    2019-07-30
  • a、
    年老代如果设置过大,会导致full gc时间过长,full gc需要stop-the-world,程序会出现长时间停顿。如果年轻代设置过大,因为年轻代用的是标记-复制算法,所以会出现需要复制大量数据的情况,也需要stop-the-world,所以也会出现长时间停顿
    2019-07-30
    1
收起评论
19
返回
顶部