部分内容参考自CSDN

测试环境通过agent注入了部分代码,其中包括几个Timer.

在通过启动脚本重启tomcat时,会一直有一个stop进程卡住,导致tomcat无法正常重启,进程卡住不动。

通过jstack tomcat进程,发现没有死锁进程,只有两个进程是TIMED_WAITING,这两个进程是通过agent注入的两个原生timer,原生timer很不建议使用.

        /**
* 1.获取路由节点队列数据,超过Config.Message.NODES大小发送至GRCC
*/
new Timer("route-nodes-to-grcc-timer-1").scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
try {
while (true) {
try {
if(isCanPoll){
Node node = nodesLinkedQueue.poll();
if(null != node){
nodes.add(node);
if(nodes.size() >= Config.Message.NODES){
try{
semaphore.acquire();
if(!nodes.isEmpty()){
sendToGRCC(nodes);
}
}catch (Exception e){
logger.error("Consumer Task发送链路信息至GRCC异常,异常信息如下:"+e.getMessage());
}finally {
semaphore.release();
}
}
}
}
Thread.sleep(10L);
} catch (Exception e) {
logger.error("nodesLinkedQueue poll异常,错误信息如下:"+e.getMessage());
}
}
} catch (Exception e) {
logger.error("schedule执行异常,错误信息如下:"+e.getMessage());
}
}
}, 1000L, 1000L); /**
* 2.间隔Config.Message.INTERVAL时间发送一次路由节点信息至GRCC
*/
new Timer("route-nodes-to-grcc-timer-2").scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
/**
* nodes不为null再获取锁进行发送
*/
if (!nodes.isEmpty()) {
try {
semaphore.acquire();
isCanPoll = false;
if (!nodes.isEmpty()) {
sendToGRCC(nodes);
}
} catch (Exception e) {
logger.error("Schedule Task发送链路信息至GRCC异常,异常信息如下:" + e.getMessage());
} finally {
semaphore.release();
isCanPoll = true;
}
}
}
},1000L,Config.Message.INTERVAL);

每次tomcat重启时,进程卡住的同时,后端tomcat日志会打印如下类似的提示内存泄漏的warning:

02-Jan-2019 19:37:46.918 警告 [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [fx-route] appears to have started a thread named [dubbo-remoting-client-heartbeat-thread-2] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
java.lang.Thread.run(Thread.java:745)
02-Jan-2019 19:37:46.920 警告 [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [fx-route] appears to have started a thread named [pool-13-thread-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
java.lang.Thread.run(Thread.java:745)
02-Jan-2019 19:37:46.922 警告 [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [fx-route] appears to have started a thread named [pool-14-thread-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
java.lang.Thread.run(Thread.java:745)
02-Jan-2019 19:37:46.923 警告 [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [fx-route] appears to have started a thread named [Abandoned connection cleanup thread] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
java.lang.Object.wait(Native Method)
java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
com.mysql.jdbc.NonRegisteringDriver$1.run(NonRegisteringDriver.java:93)

通过查询,发现上述CSDN中描述的:存在线程未关闭,比如Timer

后来将Timer修改为ScheduledExecutorService后,发现tomcat启动正常。

ScheduledExecutorService executor =  Executors.newScheduledThreadPool(2,new DefaultNamedThreadFactory("route-nodes-to-grcc"));
/**
* 1.获取路由节点队列数据,超过Config.Message.NODES大小发送至GRCC
*/
executor.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
while (true) {
try {
if(isCanPoll){
Node node = nodesLinkedQueue.poll();
if(null != node){
nodes.add(node);
if(nodes.size() >= Config.Message.NODES){
try{
semaphore.acquire();
if(!nodes.isEmpty()){
sendToGRCC(nodes);
}
}catch (Exception e){
logger.error("Consumer Task发送链路信息至GRCC异常,异常信息如下:"+e.getMessage());
}finally {
semaphore.release();
}
}
}
}
Thread.sleep(10L);
} catch (Exception e) {
logger.error("nodesLinkedQueue poll异常,错误信息如下:"+e.getMessage());
}
}
} catch (Exception e) {
logger.error("schedule执行异常,错误信息如下:"+e.getMessage());
}
}
},1000L, 1000L, TimeUnit.MILLISECONDS); /**
* 2.间隔Config.Message.INTERVAL时间发送一次路由节点信息至GRCC
*/
executor.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
/**
* nodes不为null再获取锁进行发送
*/
if (!nodes.isEmpty()) {
try {
semaphore.acquire();
isCanPoll = false;
if (!nodes.isEmpty()) {
sendToGRCC(nodes);
}
} catch (Exception e) {
logger.error("Schedule Task发送链路信息至GRCC异常,异常信息如下:" + e.getMessage());
} finally {
semaphore.release();
isCanPoll = true;
}
}
}
},1000L,Config.Message.INTERVAL,TimeUnit.MILLISECONDS);

阿里编程规范有如下两条:

    • 【规范】线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。
      说明:使用线程池的好处是减少在创建和销毁线程上所花的时间以及系统资源的开销,解决资源不足的问题。如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或者 “过度切换”的问题。
    • 【规范】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。 
      说明:Executors 返回的线程池对象的弊端如下:
      1)FixedThreadPool 和 SingleThreadPool:
        允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
      2)CachedThreadPool 和 ScheduledThreadPool:
             允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。

记Tomcat进程stop卡住问题定位处理的更多相关文章

  1. (转)tomcat进程意外退出的问题分析

    节前某个部门的测试环境反馈tomcat会意外退出,我们到实际环境排查后发现不是jvm crash,日志里有进程销毁的记录,从pause到destory的整个过程: org.apache.coyote. ...

  2. window 和 linux 环境下杀死tomcat进程——也可以解决其他端口被占用的问题

    1.应用场景 在Windows或者linux操作系统中,我们在启动一个tomcat服务器时,经常会发现8080端口已经被占用的错误,而我们又不知道如何停止这个tomcat服务器. 2.window环境 ...

  3. 在Windows操作系统中,如何终止占有的8080端口的tomcat进程

    在Windows操作系统中,我们在启动一个tomcat服务器时,经常会发现8080端口已经被占用的错误,而我们又不知道如何停止这个tomcat服务器. 本文将通过命令来强行终止这个已经运行的tomca ...

  4. linux下shutdown无法关闭tomcat进程的解决方式

    1.问题 笔者在linux下发现使用tomcat6.0.41自带的./shutdown.sh常常无法停止进程,导致各种问题的发生,令笔者相当反感! 2.解决方式一: 查找到全部的tomcat进程 $ ...

  5. Linux下tomcat管理查看控制台|杀死tomcat进程

    查看控制台 # tail -f catalina.out 脚本执行权限chmod u+x *.sh #看是否已经有tomcat在运行了 ps -ef |grep tomcat #如果有,用kill; ...

  6. windows和linux下关闭Tomcat进程

    windows和linux下解决Tomcat进程 windows下启动Tomcat报错,8080端口号被占用,报错信息如下 两种解决方法,一种是关闭了这个端口号,另外一种是修改Tomcat下的serv ...

  7. tomcat 进程莫名停止

    背景: 有一次晚上下班,发完版,刚把电脑合上走到楼下,就接到报警,说是线上有一个tomcat进程不存在了,想着以为是误报,但是还是回去看看了,发现线上确实是刚才发版的项目,进程不存在了,想了想,刚才测 ...

  8. tomcat启动时卡住

    tomcat启动时卡住 进入jdk/jre/lib/security/java.security文件 找到securerandom.source将这一行隐藏 并在下面一行加入securerandom. ...

  9. jstat命令查看tomcat进程提示进程没找到(PID not found

    今天遇到了一个小问题,我想用jstat命令查看tomcat进程(PID=24493)的内存使用情况,命令如下:jstat -gc 24493. 然后就报错了,错误提示信息为 24493 not fou ...

随机推荐

  1. Bzoj3073Journeys

    这不裸的dij吗?来,弄他. 打完以后发现不妙,这数据范围略神奇……算一算,考一场都可能跑不出来.map去重边(成功额外引入log)不怕,交.TLE,54. 这不玩呢吗,把map去了,交.MLE,71 ...

  2. Requests 代理池

    Requests 本身不提供代理池,然而爬数据又要用,所以只能自己搞.其实还挺简单的.我也不知道为什么这么有用的 feature 一直没有被加入. import requests class Clie ...

  3. spring自定义自动配置注解

    我们知道springboot自动配置@EnableAutoConfiguration是通过@Import(AutoConfigurationImportSelector.class)来把自动配置组件加 ...

  4. LC 763. Partition Labels

    A string S of lowercase letters is given. We want to partition this string into as many parts as pos ...

  5. python - 技术提高要点之一,函数式编程,性能,测试和编码规范

    摘自:http://www.cnblogs.com/kaituorensheng/p/4516983.html 函数式编程 命令式的编程风格已经成为事实上的标准.命令式编程的程序是由一些描述状态转变的 ...

  6. SQLite 版本引发的 Python 程序调用问题

    问题 在跑 OpenStack functional 功能测试的时候有两个用例过不去. nova.tests.functional.db.test_resource_provider.Resource ...

  7. 解决 JDK1.7 不支持 VCenter 6.7 的问题(涉及到Https TLS1.2协议)

    解决 JDK1.7 不支持 VCenter 6.7 的问题 问题描述 原项目工程是使用JDK 1.7,可以连接 5.X版本和 6.0版本的 VCenter资源池. 但是,现在VCenter已经升到 6 ...

  8. python programming作业11 Qt designer (打地鼠,不是很完美)

     不导包的代码 from PyQt5 import QtCore, QtGui, QtWidgets import sys from PyQt5.QtWidgets import QApplicati ...

  9. spring boot系列(一)spring boot 初识

    什么是spring boot Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员 ...

  10. Python:Base2(List和Tuple类型, 条件判断和循环,Dict和Set类型)

    1.Python创建list: Python内置的一种数据类型是列表:list.list是一种有序的集合,可以随时添加和删除其中的元素. 比如,列出班里所有同学的名字,就可以用一个list表示: &g ...