tomcat7内存泄漏
Tomcat7 它增加了一个内存泄漏的检查,主要是判断web应用重载时,类加载器中所有对象的引用都释放干净。
一般出现提示可能的原因:
1.JDBC驱动注册
2.一些日志框架
3.在ThreadLocal中保存对象,但是并不去删除它
4.启动了线程,但没有停止它
解决方法可能就是对应的应用需要加一个 ServletContextListener ,然后在 contextDestroyed 方法里去把以上的事情做掉。比如如果你用到了jdbc,那么需要手动去注销jdbc。threadlocal的保存的对象把它们清空掉。等等等等。。。
要具体问题具体分析。当然也可以不做什么事情。其实也没有多大关系的。
这里的内存泄漏指的也是你在不重新启动tomcat的情况下,reload某一个应用,才会造成内存泄漏。所以你只要每次重启应用都是通过重启tomcat来的话不会造成任何影响。
tomcat有时候会遇到所有操作都响应很慢,或者一直没有响应的情况。如果这个时候通过日志无法看到错误信息。可能就不好分析问题出处。
这种情况可以看一下tomcat的线程信息,看看都是在进行什么操作。
参考网址https://www.cnblogs.com/shengulong/p/8513652.html
jstack 线程ID 可以查看某个线程的堆栈情况,特别对于hung挂死的线程,可以使用选项-F强制打印dump信息jstack -F pid
jstack定义: jstack是java虚拟机自带的一种堆栈跟踪工具。用于生成java虚拟机当前时刻的线程快照。线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。
PS : 在实际运行中,往往一次 dump的信息,还不足以确认问题。建议产生三次 dump信息,如果每次 dump都指向同一个问题,我们才确定问题的典型性。也就是多进行几次线程快照,观察变化,查看问题所在。
参考命令 jstack pid >run.log 然后把run.log文件用附件“查看线程日志”工具打开。
主要观察几种状态
- 死锁,Deadlock(重点关注)
- 执行中,Runnable
- 等待资源,Waiting on condition(重点关注)
- 等待获取监视器,Waiting on monitor entry(重点关注)
- 暂停,Suspended
- 对象等待中,Object.wait() 或 TIMED_WAITING
- 阻塞,Blocked(重点关注)
- 停止,Parked
第一步先找出Java进程ID,服务器上的Java应用名称为mrf-center:
[email protected]:/# ps -ef | grep mrf-center | grep -v grep root 21711 1 1 14:47 pts/3 00:02:10 java -jar mrf-center.jar
得到进程ID为21711,第二步找出该进程内最耗费CPU的线程,可以使用 1)ps -Lfp pid 2)ps -mp pid -o THREAD, tid, time 3)top -Hp pid 用第三个,输出如下:
TIME列就是各个Java线程耗费的CPU时间,CPU时间最长的是线程ID为21742的线程,用
#printf "%x\n" 21742
得到21742的十六进制值为54ee,下面会用到。
OK,下一步终于轮到jstack上场了,它用来输出进程21711的堆栈信息,然后根据线程ID的十六进制值grep,如下:
# jstack 21711 | grep 54ee "PollIntervalRetrySchedulerThread" prio=10 tid=0x00007f950043e000 nid=0x54ee in Object.wait()
可以看到CPU消耗在PollIntervalRetrySchedulerThread这个类的Object.wait(),我找了下我的代码,定位到下面的代码:
// Idle wait getLog().info("Thread [" + getName() + "] is idle waiting..."); schedulerThreadState = PollTaskSchedulerThreadState.IdleWaiting; long now = System.currentTimeMillis(); long waitTime = now + getIdleWaitTime(); long timeUntilContinue = waitTime - now; synchronized(sigLock) { try { if(!halted.get()) { sigLock.wait(timeUntilContinue); } } catch (InterruptedException ignore) { } }
它是轮询任务的空闲等待代码,上面的sigLock.wait(timeUntilContinue)就对应了前面的Object.wait()。
原文地址:https://www.cnblogs.com/shuaishuai1993/p/9205411.html