深入拆解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
登录|注册

37 | Tomcat内存溢出的原因分析及调优

李号双 2019-08-06
作为 Java 程序员,我们几乎都会碰到 java.lang.OutOfMemoryError 异常,但是你知道有哪些原因可能导致 JVM 抛出 OutOfMemoryError 异常吗?
JVM 在抛出 java.lang.OutOfMemoryError 时,除了会打印出一行描述信息,还会打印堆栈跟踪,因此我们可以通过这些信息来找到导致异常的原因。在寻找原因前,我们先来看看有哪些因素会导致 OutOfMemoryError,其中内存泄漏是导致 OutOfMemoryError 的一个比较常见的原因,最后我们通过一个实战案例来定位内存泄漏。

内存溢出场景及方案

java.lang.OutOfMemoryError: Java heap space
JVM 无法在堆中分配对象时,会抛出这个异常,导致这个异常的原因可能有三种:
内存泄漏。Java 应用程序一直持有 Java 对象的引用,导致对象无法被 GC 回收,比如对象池和内存池中的对象无法被 GC 回收。
配置问题。有可能是我们通过 JVM 参数指定的堆大小(或者未指定的默认大小),对于应用程序来说是不够的。解决办法是通过 JVM 参数加大堆的大小。
finalize 方法的过度使用。如果我们想在 Java 类实例被 GC 之前执行一些逻辑,比如清理对象持有的资源,可以在 Java 类中定义 finalize 方法,这样 JVM GC 不会立即回收这些对象实例,而是将对象实例添加到一个叫“java.lang.ref.Finalizer.ReferenceQueue”的队列中,执行对象的 finalize 方法,之后才会回收这些对象。Finalizer 线程会和主线程竞争 CPU 资源,但由于优先级低,所以处理速度跟不上主线程创建对象的速度,因此 ReferenceQueue 队列中的对象就越来越多,最终会抛出 OutOfMemoryError。解决办法是尽量不要给 Java 类定义 finalize 方法。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《深入拆解Tomcat & Jetty 》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(8)

  • 广训
    刚入职现在的公司,发现线上某个实例会不定期不提供服务,进程还在,但是不再接受请求。每次都重启就恢复,后来一直观察。线上没写权限,也没什么监控工具,就是那种突然出问题,还要临时申请写权限去机器上执行jvm的相关命令。有时候也抱怨权限这东西,就跟站着茅坑不拉屎一样搞笑,有权限的人不做,要做的人做不了。有次用eclipse的工具看了下,dubbo对象特别多,都超过spring boot的了,看了dubbo的代码,发觉居然是每次都new出Reference来的,没有用注解,没有交给spring接管。交给容器后,后来也出现过服务不可用。一次偶然的机会,排查另一个问题时发现mybatis数据库异常,分析日志得知一个sql查询足足执行了30多分钟,看了sql语句,where条件触发了全表超大量数据扫描,然后服务就撑差不多半小时,异常之前服务是正常提供的,直到oom时僵尸。因为订单表订单号是拆单,父订单的父订单号自然为0,有一些老订单数据不符合规范,导致查询了订单号为0的sql。本地模拟果不其然,执行半个小时后就oom,服务不可用。oom是标准输出,日志并无该提示,导致一直未能看到。就加了一个if订单号不为0就解决了,你说这代码写的,找谁说理去。这个问题足足留意了差不多2个月,才找到是这么个原因,居然骂人都没脾气的问题。
    2019-08-07
    5
  • 疯狂咸鱼
    老师的这门课太值了啊,可能很多人看到只是是tomcat所以没来买这门课,但是老师的课程里涉及到到了java的方方面面,真的是如获至宝。

    作者回复: 谢谢夸奖😄

    2019-08-16
    3
  • QQ怪
    之前在使用es的时候想用线程池来优化频繁获取连接造成的资源浪费,但因为自己粗心,使用的过程中错误的操作获取连接都去new线程池,而不是从线程池获取线程,导致内存老是到顶,那次内存泄露还是自己的基本功不扎实导致的,最后也是通过一些jvm工具找到了问题,当时画了不少时间在上面,挺感慨的
    2019-08-06
    3
  • neohope
    YGC 表示 Minor GC 的总时间,YGCT 表示 Minor GC 的次数。这两个是写反了吗?
    2019-08-06
    1
  • 星辰
    赞 自己手还是比较生 了解到的知识面比较窄 还是要多记 多理解 多联系 无奈平时的增删改查太多了
    2019-08-06
    1
  • 靠人品去赢
    这个精确到每个“每个 out of memory”,很顶哦。
    2019-12-04
  • 张德
    最常见的内存溢出的原因 比如递归的时候 没有出口
    2019-10-24
  • Geek_00d567
    大部分是jvm的原因啊,好想没tomcat啥事啊。老师的课程,实战性很强。
    2019-09-19
收起评论
8
返回
顶部