【转】一次由过量线程引发的OOM排查
mac的话,还得进行下特殊处理:右键mat显示包内容,进入Contents->MacOS下面,会有一个MemoryAnalyzer的命令。
打开终端,进入此路径找到MemoryAnalyzer,运行 ./MemoryAnalyzer -data ./dump
最近,公司的系统老是出现定时任务延迟执行的情况,一开始以为是由于基本上在那个点,需要执行的任务过多,而执行线程只有一个引起的正常列队(用的是springtask的定时任务,默认配置的线程池中最大线程数量为1),但在一个月黑风高的夜晚,客户反应没有任何的产品上架,而且已经离定时上架任务执行的时间过去了1个多小时,感觉肯定是系统出现了不可描述的问题。(由于没带电脑回家,是第二天去公司做的调试,当时以手动上架的方式先解决燃眉之急)
第一步:查询了下完整的tomcat输出日志,发现了出现停顿的问题,就是OutOfMemoryError,如图:
第二步:发生停顿的时间是在15号23.00左右,刚好是执行产品上架的时间,然后继续往下看日志,发现日志输出的时间有问题:
第三步:所以可以推测,其实当时日志写入的时候,真正时间已经是16号00:21分,但由于以前阻塞的线程现在才开始继续活动,所以记录的还是他阻塞时候获得的时间;而且看default.log也能发现,15号23:00之后,就没有任何的日志输出,其实整个系统都已经处于挂起状态,所以联想到造成整个系统停止的原因应该是FullGC引起的,立马去看了下系统的gc情况(因为tomcat没有配gc日志输出,所以没法跟踪到当时的gc情况,只能看gc的总输出):
看到总共做了18111次的FullGC,停顿时间5627秒,超过一个半小时。。。(瑟瑟发抖)
第四步:用指令:jmap -heap pid ,查看当前的内存使用情况,发现内存还是很吃紧,说明问题其实还是存在的;
第五步:用指令: jmap -dump:format=b,file=fileName pid 获取下内存文件,然后下载到本地,再用eclipse的MAT内存分析工具进行分析,刚打开,就发现问题所在:
Thead线程对象竟然创建了226M,而系统运行的总内存也就512M,所以问题一定是在线程的创建上了,继续往下看,打开overview ——>Actions中的Histogram:看到是byte[]所占的内存最多,继续追踪byte[]的生成对象,
发现这2个所占的容量是最大的,继续点开,查看调用追踪,发现上面那个反射对象,应该是框架自身使用的原因,不是异常;
下面那个com.jcraft.jsch.Session经查代码,发现是连接sftp的一个session对象,而且他自身实现了RunAble接口,所以start之后,本身就是一个运行的线程,如果没有被正确关闭,就会运行停留代码里面设置的时间,所以在这期间,是不会被GC回收的;
继续看代码,发现确实是获取sftpChannel对象的方式有问题,如果在getChannel()方法中,发生异常,导致session已经启动,但返回的channel却是null,获取到的sftpChannel就是null的,也就是无法在后面进行关闭,只能等待他自己超时
所以针对上面的问题,给出的解决方案是,在getChannel()方法中,自己进行异常的捕获,如果发生异常,就立马进行session的关闭,且加大系统的内存到1G。
注:当时为了验证GC没有回收的原因是因为线程一直在运行造成的,所以还用指令:jstack pid
获取下了线程的运行状态文件,发现确实是4800多的sftpSession的连接线程,一直处于runable中,刚好能和内存中session对象个数进行对应。。。
【转】一次由过量线程引发的OOM排查的更多相关文章
- Asp.Net正在中止线程引发的问题
背景: Asp.Net做的一个同步程序,同步的方法是通过JQuery的Ajax调用,同步过程大概要执行20多分钟,程序部署到服务器后执行一段时间后就弹出执行失败的对话框,日志记录的错误信息是“正在中止 ...
- 【心得】asp.net 异常:正在中止线程 引发的问题
asp.net做的一个同步程序,同步的方法是通过JQuery的Ajax调用,同步过程所需要的时间大概有几个小时吧. 当在本机运行的时候,无论是debug模式还是release模式,都能正常运行. 发布 ...
- 记一次线上dubbo服务超时和线程池满问题排查
线上某dubbo服务A调用dubbo服务B的接口X方法,调用端A日志中出现了很多超时的情况,提供端B该接口X超时时间设置为60s: 查看提供端B的日志,报了很多线程池满的异常: Caused by: ...
- index_merge引发的死锁排查
概述 前几天排查了一个死锁问题,最开始百思不得其解,因为发生死锁的两个事务是单语句事务,语句类型相同(where属性列相同,仅值不同),而且语句都走了相同的索引,但最终确实发生了死锁.通过定位排查发现 ...
- 详解线程池的作用及Java中如何使用线程池
服务端应用程序(如数据库和 Web 服务器)需要处理来自客户端的高并发.耗时较短的请求任务,所以频繁的创建处理这些请求的所需要的线程就是一个非常消耗资源的操作.常规的方法是针对一个新的请求创建一个新线 ...
- InvokeRequired 线程间访问
zt: http://www.x2blog.cn/jinhong618/?tid=22389 问: f (this.InvokeRequired) { ...
- 线程——委托InvokeRequired和Invoke
C#中禁止跨线程直接访问控件,InvokeRequired是为了解决这个问题而产生的,当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想访问它.此时它将会在内部调用ne ...
- C#之Winform跨线程访问控件
C#中禁止跨线程直接访问控件,InvokeRequired是为了解决这个问题而产生的,当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想访问它.此时它将会在内部调用ne ...
- JVM运行时内存组成分为一些线程私
JVM运行时内存组成分为一些线程私有的,其他的是线程共享的. 线程私有 程序计数器:当前线程所执行的字节码的行号指示器. Java虚拟机栈:java方法执行的内存模型,每个方法被执行时都会创建一个栈帧 ...
随机推荐
- L-BFGS算法介绍
可以看出,拟牛顿法每次迭代只需要根据前次迭代的即可以计算出,不需要求出Hesse矩阵的逆. 2.4 L-BFGS(limited-memory BFGS) BFGS算法中每次迭代计算需要前次迭代得到的 ...
- 附1 Java内存模型与共享变量可见性
注:本文主要参考自<深入理解Java虚拟机(第二版)>和<深入理解Java内存模型> 1.Java内存模型(JMM) Java内存模型的主要目标:定义在虚拟机中将变量存储到内存 ...
- 程序媛计划——mysql基本操作
本文适用于mac 在官网上下载community 版mysql,选择dmy这种.在终端中安装好mysql. #进入mysql /usr/local/mysql/bin/mysql -uroot -p ...
- Python 将一个已知的 utc时间字符串 转换为东八区时间
先获取一个utc格式的时间 utc_time = datetime.datetime.utcnow() print(utc_time) 输出 2018-06-24T08:59:39Z 这里我们假设目前 ...
- echarts4 主题切换
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...
- 【JXOI2018】排序问题 贪心
我们令$sum_i$表示数字i在加完数字的数列中出现的次数,那么答案显然为$\dfrac{(n+m)!}{\sum_{i=0}^{\infty}sum_i!}$ 不难发现,当每次添加的数为$[l,r] ...
- 【bzoj4240】 有趣的家庭菜园 树状数组
这一题最终要构造的序列显然是一个单峰序列 首先有一个结论:一个序列通过交换相邻的元素,进行排序,最少的交换次数为该序列的逆序对个数 (该结论很久之前打表意外发现的,没想到用上了.....) 考虑如何构 ...
- 《Head First 设计模式》读书笔记
目录 <Head First 设计模式>读书笔记 创建模式 结构模式 行为模式 用思维导图记录的读书笔记. <Head First 设计模式>读书笔记 模式的分类遵循<设 ...
- c#连接oracle的几种方式
一:通过System.Data.OracleClient(需要安装Oracle客户端并配置tnsnames.ora)1. 添加命名空间System.Data.OracleClient引用2. usin ...
- 在Mac OS X上启用Apache和PHP
因为Mac OS X上都已自带了Apache和PHP,所以都无需进行安装,只要按照自己的需要进行设置即可. 找到httpd.conf文件,并用编辑器打开. 加载PHP模块.找到 #LoadModule ...