【转】一次由过量线程引发的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方法执行的内存模型,每个方法被执行时都会创建一个栈帧 ...
随机推荐
- NGUI图集字体
UIFont里使用Symbols来指定字体时用Sprite前缀和名字自动分配的工具,前段时间工作需要时写的,具体用法有空时再写. using UnityEngine; using UnityEdito ...
- python 简单搭建阻塞式单进程,多进程,多线程服务
由于经常被抓取文章内容,在此附上博客文章网址:,偶尔会更新某些出错的数据或文字,建议到我博客地址 : --> 点击这里 我们可以通过这样子的方式去理解apache的工作原理 1 单进程TCP服 ...
- 双向链表的实现——java
实现类: /** * Java 实现的双向链表. * 注:java自带的集合包中有实现双向链表,路径是:java.util.LinkedList * * @author skywang * @date ...
- sublime-text-how-to-jump-to-file-from-find-results-using-keyboard
http://209.116.186.231/#newwindow=1&q=sublime+text+find+results+jump http://stackoverflow.com/qu ...
- (2)Oracle基础--表空间
· 表空间概述 <1> 理解表空间 ① 表空间与数据库的关系: 表空间是数据库的逻辑存储空间,可以理解为在数据库中开辟的一块空间,用于存放数据库的对象. 一个数据库可以由多个表空间构成.O ...
- webpack快速入门——实战技巧:优雅打包第三方类库
下面说两种方法: 一. 1.引入jQuery,首先安装: cnpm install --save jquery 2.安装好后,在我们的entry.js中引入: import $ from 'jquer ...
- HashMap、HashSet、LinkedHashSet、TreeSet的关系
类图及说明如下:
- Xshell 命令后台执行
但是这样没有在后台启动:因此sh那一行代码需要修改: 前边加上nohup 后边加上& nohup dotnet helloword.dll & 然后,进程启动之后,按任意键进入输入状态 ...
- 使用Intent在活动之间穿梭
使用Intent在活动之间穿梭 1.在com.example.activitytest中创建第二个活动SecondActivity: /** * 第二个活动 */ public class Secon ...
- 一桩由X509Certificate2引发的血案
A process serving application pool '. The data field contains the error number. 在某次网站更新后,发现wcf服务不可用了 ...