部分内容参考自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. 11.二进制中1的个数 Java

    题目描述 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. 思路 当n不等于0时执行以下循环: 1.判断n的最低位是否为1,若为1,则计数器加1 2.将n无符号右移1位(若使用带符号移 ...

  2. TCP之RST报文段

    TCP 首部中的 RST 比特是用于 "复位" 的.一般来说,无论何时一个报文段发往基准的连接(referenced connection)出现错误,TCP 都会发出一个复位报文段 ...

  3. D建立app项目(mui)

    参考 http://dev.dcloud.net.cn/mui/getting-started/ 1.ios需要下载iTunes,确保手机能连上电脑 2.mui可参考手册 http://dev.dcl ...

  4. websphere gc策略调整

    根据应用服务器处理的特性,适配不同的gc策略,验证程序最适合程序的gc策略: server.xml路径: xmlcells/PBOCCell/nodes/PBOCNode01/servers/PBOC ...

  5. leetcode-hard-array-76. Minimum Window Substring -NO

    mycode 不会.. 参考: class Solution(object): def minWindow(self, s, t): """ :type s: str : ...

  6. apt 软件安装问题

    1.sudo apt-get update由于没有公钥,无法验证下列签名: NO_PUBKEY F42ED6FBAB17C654 解决方法:安装公钥 sudo apt-key adv --keyser ...

  7. JScript 程序流程控制

    Jscript 脚本中的语句一般是按照写的顺序来运行的.这种运行称为顺序运行,是程序流的默认方向. 与顺序运行不同,另一种运行将程序流转换到脚本的另外的部分.也就是,不按顺序运行下一条语句,而是运行另 ...

  8. PreparedStatement执行sql語句

    import com.loaderman.util.JdbcUtil; import java.sql.Connection; import java.sql.PreparedStatement; i ...

  9. spring_quartz的实现

    一.在spring配置文件中引用对应的定时任务配置文件 二.定义定时任务的业务代码 三.配置定时任务配置文件spring-quartz.xml <?xml version="1.0&q ...

  10. kubernetes学习:CKA考试认证(二)

    1. 它题的意思是 在 development 名称空间里面 找到名为 baz的 service 然后通过这个service的selector 找出 对应的pod . 要用   kubectl des ...