memory leak-----tomcat日志warn
web应用借助于结构:spring mvc + quartz结构,部署到tomcat容器时,shutdown时的error信息:
appears to have started a thread named [schedulerFactoryBean_Worker-1] but has failed to stop it. This is very likely to create a memory leak
quartz的thread终止的确保,加了个servletListener,工作就是显示的使用shutdown方法:
@Override
public void contextDestroyed(ServletContextEvent sce) {
LogAgent.debug(LoggerEnum.SYS_INFO, "QUARTZ.context destroy start.");
WebApplicationContext webApplicationContext = (WebApplicationContext) sce.getServletContext()
.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); org.springframework.scheduling.quartz.SchedulerFactoryBean fact = (org.springframework.scheduling.quartz.SchedulerFactoryBean) webApplicationContext
.getBean("schedulerFactoryBean");
if (fact != null) {
try {
LogAgent.debug(LoggerEnum.SYS_INFO, "shedule shutdown start.");
fact.getScheduler().shutdown();
LogAgent.debug(LoggerEnum.SYS_INFO, "shedule shutdown end.");
} catch (SchedulerException e) {
LogAgent.error(LoggerEnum.ERROR_INFO, e);
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
LogAgent.error(LoggerEnum.ERROR_INFO, e);
}
LogAgent.debug(LoggerEnum.SYS_INFO, "QUARTZ.context destroy end.");
}
接着的提示信息:
created a ThreadLocal with key of type [org.apache.commons.lang.builder.ReflectionToStringBuilder$1] (value [org.apache.commons.lang.builder.ReflectionToStringBuilder$1@1a08777c]) and a value of type [java.util.HashSet] (value [[]]) but failed to remove it when the web application was stopped. This is very likely to create a memory leak.
检查了代码,发现日志输出的部分,有个类使用了类:org.apache.commons.lang.builder.ToStringBuilder,其内部实现使用了org.apache.commons.lang.builder.ReflectionToStringBuilder,再跟进的时候发现,ToStringBuilder的append方法,在append和toString的时候,向ToStringStyle register或unregister(就是threadlocal的set obj和 remove);跟踪代码时发现明显该threadlocal在每次toString时都有remove,不应该会出现leak memory的倾向才对(若运行一半异常还是有可能,但该方法就是一个日志记录,所以无这方面的担心),最后检查pom时发现,commons-lang有两个包,分别是appache-lang和commons-lang:jar名都是commons-lang,删掉appache-lang的这个warn警告就没出现了(我也不记得了,为什么会引入两个commons-lang)。
结果再运行时,发现另一个错误了:
信息: Illegal access: this web application instance has been stopped already. Could not load ch.qos.logback.core.status.WarnStatus. The eventual following stack trace is caused by an error thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access, and has no functional impact.
java.lang.IllegalStateException
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1588)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1547)
at ch.qos.logback.classic.LoggerContext.noAppenderDefinedWarning(LoggerContext.java:175)
at ch.qos.logback.classic.Logger.callAppenders(Logger.java:267)
at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:442)
at ch.qos.logback.classic.Logger.filterAndLog_0_Or3Plus(Logger.java:396)
at ch.qos.logback.classic.Logger.debug(Logger.java:503)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:612)
首先级别上来看,是信息,不是错误;
但是本着看到error stack就不爽的本质,了解了一把,原因大致如此:
- quartz的SimpleThreadPool在初始化的时候,启动了一定数量的线程:WorkerThread,然后它就让WorkerThread自己滴去干活了。
- 然后当容器发出shutdown的信号时,pool就告诉workerthread们,要shutdown了,现在问题来了,看代码:
/**
* <p>
* Signal the thread that it should terminate.
* </p>
*/
void shutdown() {
run.set(false);
}
很明显,这就是它的shutdown方法,它并不是要自己杀掉自己,而是告知自己的当前状态是false了,再来看看该状态作用的地方:
@Override
public void run() {
boolean ran = false; while (run.get()) {
try {
synchronized(lock) {
while (runnable == null && run.get()) {
lock.wait(500);
} if (runnable != null) {
ran = true;
runnable.run();
}
}
} catch (InterruptedException unblock) {
// do nothing (loop will terminate if shutdown() was called
try {
getLog().error("Worker thread was interrupt()'ed.", unblock);
} catch(Exception e) {
// ignore to help with a tomcat glitch
}
} catch (Throwable exceptionInRunnable) {
try {
getLog().error("Error while executing the Runnable: ",
exceptionInRunnable);
} catch(Exception e) {
// ignore to help with a tomcat glitch
}
} finally {
synchronized(lock) {
runnable = null;
}
// repair the thread in case the runnable mucked it up...
if(getPriority() != tp.getThreadPriority()) {
setPriority(tp.getThreadPriority());
} if (runOnce) {
run.set(false);
clearFromBusyWorkersList(this);
} else if(ran) {
ran = false;
makeAvailable(this);
} }
} //if (log.isDebugEnabled())
try {
getLog().debug("WorkerThread is shut down.");
} catch(Exception e) {
// ignore to help with a tomcat glitch
}
}
其实就是第5行,对run进行判断,如果是false,就直接退出了。
所以pool的shut通知并不是马上就能被执行,如果线程正好走while判断条件,马上就会被退出;
如果该thread无任务可做时,见第8行:lock.wait(500),所以会wait,这个时候再退出,结果去getLog的时候,loggerContextListener.destroy先执行,无logger了,所以会有该信息。
解决办法就是:
将log的listener放到最后(如果有多个listener的话):
<listener>
<listener-class>com.xxx.listener.QuartzLitener</listener-class>
</listener>
<listener>
<listener-class>com.xxx.web.listener.LogbackListener</listener-class>
</listener>
memory leak-----tomcat日志warn的更多相关文章
- tomcat 6.0.44 “has failed to stop it. This is very likely to create a memory leak” 问题调查
1. 问题起因 我们项目中缓存模块某个实现采用了ehcache(2.4.3),当项目部署到tomcat中后,对tomcat做停止服务操作(点击eclipse的console红色的停止按钮,奇怪的是有小 ...
- tomcat启动部署APP报错:This is very likely to create a memory leak
This is very likely to create a memory leak的错误,网上很多,原因也是各种各样,这里也仅提供一个解决的思路. 问题描述:启动tomcat时,不能访问部署的AP ...
- Tomcat运行一段时间后,自动停止关闭,To prevent a memory leak,Druid 数据库连接自动关闭, the JDBC Driver has been forcibly unregistered.
1. Tomcat 错误日志 tail -100f tomcat9/logs/catalina.out 21-Sep-2017 23:05:39.301 INFO [Thread-5] org.apa ...
- tomcat报错:This is very likely to create a memory leak问题解决
tomcat memory leak解决方案 这种问题在开发中经常会碰到的,看看前辈的总结经验 Tomcat内存溢出的原因 在生产环境中tomcat内存设置不好很容易出现内存溢出.造成内存溢出是不一 ...
- 大神的---解决tomcat内存溢出问题----tomcat报错:This is very likely to create a memory leak问题解决
tomcat memory leak解决方案 这种问题在开发中经常会碰到的,看看前辈的总结经验 Tomcat内存溢出的原因 在生产环境中tomcat内存设置不好很容易出现内存溢出.造成内存溢出是不一 ...
- ThreadLocal Memory Leak in Java web application - Tomcat
ThreadLocal variables are infamous for creating memory leaks. A memory leak in Java is amount of mem ...
- tomcat memory leak
Struts + Hibernate做项目,重新部署项目会出现Memory Leak严重报错.虽然不影响使用,但还是有风险.经实验发现是Hibernate的session没有关闭.....粗心....
- tomcat关闭时Log4j2报错 Log4j Log4j2-TF-4-Scheduled-1 memory leak
出错信息: 23-Sep-2017 17:43:18.964 警告 [main] org.apache.catalina.loader.WebappClassLoaderBase.clearRefer ...
- python 实现过滤出tomcat日志中含有ERROR 或Exception 的行并保存在另一个文件
遍历多个tomcat日志文件,找出含有ERROR 和Exception 的日志,并把该行日志输出到另一个文件中:(这里为了体现python模块导入的知识,所有建立了多个文件夹和模块) 项目结构: co ...
随机推荐
- Bootstrap-CL:进度条
ylbtech-Bootstrap-CL:进度条 1.返回顶部 1. Bootstrap 进度条 本章将讲解 Bootstrap 进度条.在本教程中,您将看到如何使用 Bootstrap 创建加载.重 ...
- VMware vSphere Client下增加虚拟机磁盘空间的方法
随着系统运维时间的增长,磁盘就日益的损耗,如果遇到虚拟机报磁盘空间不足怎么办?还好,我们可以通过磁盘阵列增加磁盘空间,然后扩容到虚拟机中去. 对于linux虚拟机磁盘扩容的方案有两种,一种就是原有的实 ...
- 6_python之路之atm购物
6_python之路之atm购物 1.程序说明:Readme.cmd supermarket 项目主目录 ├── access.log 日志文件 ├── atm atm程序 │?? ├── atm.p ...
- Spring Boot实践——多线程
多线程 Spring通过任务执行器(TaskExecutor)来实现多线程和并发编程.使用ThreadPoolTaskExecutor可实现一个基于线程池的TaskExecutor.而实际开发中任务一 ...
- update svn cache 慢
eclipse 打开了一个工程,就进行了update svn cache,弄了2个多小时了还是在进行.观察这个过程在空文件夹上也进行了不少时间,我感觉到可能方法错了.试了下关闭SVN--> sv ...
- django中文件下载(HttpResponse)
最近一个用django开发的web项目要进行数据的导入导出,所以有必要了解下. django中主要用HttpResponse将请求结果返回给浏览器,所以文件的下载也是通过改对象进行处理的,具体的一个列 ...
- jsp页面获取地址栏中的参数
- Linux 入侵检测
一.检查系统日志 检查系统错误登陆日志,统计IP重试次数 # 这里使用了lastb命令,该命令需要root权限,可以显示所有登陆信息.这里仅仅显示的root用户的,读者可以更具实际情况自行确定,或者直 ...
- 【BZOJ3489】A simple rmq problem【kd树】
题意 给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过一次的数,并且要求找的这个数尽可能大.如果找不到这样的数,则直接输出0.我会采取一些措施强制在线. 分析 预处理 ...
- jekins测试环境自动化
最近搭建测试环境自动化,之前都是用机器猫.机器猫的流程大概是这样,开发打包上传到svn,给测试一个svn地址,测试到机器猫上传文件,然后再运行启动. 为了减去开发打包这个环节,所以专用jenkins. ...