文档章节

JreMemoryLeakPreventionListener引发的报错问题

T
 Tomax
发布于 2016/10/09 15:12
字数 717
阅读 22
收藏 0
点赞 0
评论 0

There is a memory leak detection feature introduced in Tomcat 6.0.25 that attempts to log objects that have failed to be unregistered by webapps it hosts when they are stopped, and were forcibly unregistered by Tomcat. As Tomcat is forcibly removing these objects, it is not a serious concern that these log messages occur.

停止tomcat服务后,报出以下错误:

严重: The web application [] appears to have started a thread named [Timer-0] but has failed to stop it. This is very likely to create a memory leak.
2016-9-27 21:33:48 org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
严重: The web application [] appears to have started a thread named [pool-1-thread-1] but has failed to stop it. This is very likely to create a memory leak.
2016-9-27 21:33:48 org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
严重: The web application [] appears to have started a thread named [DefaultQuartzScheduler_Worker-2] but has failed to stop it. This is very likely to create a memory leak.
2016-9-27 21:33:48 org.apache.catalina.loader.WebappClassLoader clearReferencesThreads

初步诊断为服务停止时,线程池未能成功关闭,添加线程监听器ThreadListener,在服务停止的时候停止线程池:

public class ThreadListener implements ServletContextListener {

	private Log logger = LogFactory.getLog(ThreadListener.class);
	
	@Override
	public void contextInitialized(ServletContextEvent sce) {
		
	}

	@Override
	public void contextDestroyed(ServletContextEvent sce) {
		try {
			logger.info("销毁线程池");
			ProtoExecutorService.getExecutor().shutdownNow();
		} catch (Exception e) {
			logger.error(String.format("销毁线程池出错,错误信息:%s", e));
			e.printStackTrace();
		}
	}
}

继续运行一段时间后发现,停止tomcat服务后仍会出现同样报错,查找资料,http://stackoverflow.com/questions/5292349/is-this-very-likely-to-create-a-memory-leak-in-tomcat ,添加清理ThreadLocal的代码:

public class ThreadLocalImmolater {

	private Log logger = LogFactory.getLog(ThreadLocalImmolater.class);

	private static ThreadLocalImmolater immolater = null;
	
    Boolean debug;

    public ThreadLocalImmolater() {
        debug = false;
    }
    
    public synchronized static ThreadLocalImmolater getInstance(){
    	if(null == immolater){
    		immolater = new ThreadLocalImmolater();
    	}
    	return immolater;
    }
    
    public Integer immolate() throws Exception {
        int count = 0;
        final Field threadLocalsField = Thread.class.getDeclaredField("threadLocals");
        threadLocalsField.setAccessible(true);
        final Field inheritableThreadLocalsField = Thread.class.getDeclaredField("inheritableThreadLocals");
        inheritableThreadLocalsField.setAccessible(true);
        for (final Thread thread : Thread.getAllStackTraces().keySet()) {
            count += clear(threadLocalsField.get(thread));
            count += clear(inheritableThreadLocalsField.get(thread));
            
            if (thread != null) {
            	thread.setContextClassLoader(null);
            }
        }
        logger.info("immolated " + count + " values in ThreadLocals");
        return count;
    }

    private int clear(final Object threadLocalMap) throws Exception {
        if (threadLocalMap == null)
                return 0;
        int count = 0;
        final Field tableField = threadLocalMap.getClass().getDeclaredField("table");
        tableField.setAccessible(true);
        final Object table = tableField.get(threadLocalMap);
        for (int i = 0, length = Array.getLength(table); i < length; ++i) {
            final Object entry = Array.get(table, i);
            if (entry != null) {
                final Object threadLocal = ((WeakReference)entry).get();
                if (threadLocal != null) {
                    log(i, threadLocal);
                    Array.set(table, i, null);
                    ++count;
                }
            }
        }
        return count;
    }

    private void log(int i, final Object threadLocal) {
        if (!debug) {
            return;
        }
        if (threadLocal.getClass() != null &&
            threadLocal.getClass().getEnclosingClass() != null &&
            threadLocal.getClass().getEnclosingClass().getName() != null) {

            logger.info("threadLocalMap(" + i + "): " +
                        threadLocal.getClass().getEnclosingClass().getName());
        }
        else if (threadLocal.getClass() != null &&
                 threadLocal.getClass().getName() != null) {
            logger.info("threadLocalMap(" + i + "): " + threadLocal.getClass().getName());
        }
        else {
            logger.info("threadLocalMap(" + i + "): cannot identify threadlocal class name");
        }
    }

}

在ThreadListener中添加以下代码:

//清理线程
try {
	logger.info("清理线程");
	ThreadLocalImmolater.getInstance().immolate();
} catch (Exception e) {
	logger.error(String.format("清理线程出错,错误信息:%s", e));
	e.printStackTrace();
}

运行一段时间后发现,停止tomcat服务后不再出现同样错误,但是会出现

严重: The web application [] registered the JDBC driver [com.microsoft.sqlserver.jdbc.SQLServerDriver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.

在ThreadListener中添加以下代码:

logger.info("关闭数据库连接");
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
	Driver driver = drivers.nextElement();
	try {
		DriverManager.deregisterDriver(driver);
		logger.info(String.format("deregistering jdbc driver: %s", driver));
	} catch (SQLException e) {
		logger.error(String.format("Error deregistering driver %s", driver), e);
	}

}

报错消失。

参考资料:

http://fourfireliu.iteye.com/blog/2187584

http://stackoverflow.com/questions/5292349/is-this-very-likely-to-create-a-memory-leak-in-tomcat

© 著作权归作者所有

共有 人打赏支持
T
粉丝 0
博文 5
码字总数 4372
作品 0
西安
tomcat,JreMemoryLeakPreventionListener类执行DriverManager.getDrivers()作用

tomcat的JreMemoryLeakPreventionListener类有个疑问,程序里调用了DriverManager来防止不正确的加载。但是DriverManager属于jdk/lib目录下jar里的类,在tomcat的类加载模型里,线程进入web...

_鱼_ ⋅ 2017/12/06 ⋅ 1

Tomcat的JreMemoryLeakPreventionListener1小时执行一次fu...

工作遇到每小时一次的full gc问题,并且一次运行8秒,影响体验。故转来一篇日志,Mark一下 项目部署在Tomcat7上,操作系统是centOS5.5,打印出gc的日志,发现有些full gc在heap还很空余的时候...

来吧 ⋅ 2013/08/06 ⋅ 0

tomcat内存泄露问题解决方法

今天服务器上的网站项目打不开了,使用工具打开了tomcat的日志查找bug,在排除前台页面登陆按钮出现问题和数据库崩溃和后台逻辑没有问题后,发现是内存泄露引起的。上网百度和谷歌寻找解决方...

ZICK_ZEON ⋅ 2014/04/21 ⋅ 0

Tomcat6.0的Thisisverylikelytocreateamemoryleak异常

從Apache Tomcat 5.5升級到6.0,通常不用太大的修改,原有的Web Application就能繼續運作。不過在server.xml中設定MySQL Datasource,卻出現一串惱人的警告訊息: 2010/8/6 下午 01:54:11 o...

again-Y ⋅ 2013/11/02 ⋅ 0

实现CStack类遇到的问题

自己动手编写一个CStack类,包括头文件CStack.h以及源文件CStack.cpp。 遇到了几个问题: 1.每个文件都要写using namespace std;没写的文件会报错:缺少类型说明符……(这不是废话吗。。可是...

shs0708 ⋅ 2016/04/18 ⋅ 0

.NET移植Mono初体验

序论:关于mono的介绍可以猛击这里了解!如果你因为licence的问题而对mono望而却步,你可以仔细看下这里,之后你就会大胆的去用了! 最近为了练习做了一个简单的三层架构的信息管理系统,除了...

mszhangxuefei ⋅ 2011/11/18 ⋅ 0

Symfony2.5开发常见错误

最近正在用Symfony2.5框架写一个境外电子商务项目,搭配webseverse编写相关接口;还好对方已经提供了相关接口,我只用写前段接口就好,但是用Symfony2.5操作数据库也是相当简单的;我接触过相...

晓军知了 ⋅ 2014/12/08 ⋅ 0

layui 2.2.4 发布,优化了较多问题

该版本对之前存在的较多问题进行了一次清理,推荐升级。 新增 form 的 name 为数组格式( 如:name="arr[]" )的支持 修复 form 的 select/checkbox/radio 等元素设定 lay-verType="tips" 时...

贤心 ⋅ 2017/12/08 ⋅ 19

windows系统sysperp封装提示发生致命错误解决方法

我们制作系统镜像模板的时候,可能需要多次使用sysprep进行系统封装,但是几次过后,就会提示“发生致命错误”导致封装无法继续下去。 主要是我们使用Sysprep工具进行封装的时候,会减少“W...

水幕青辰 ⋅ 2016/11/10 ⋅ 0

【JDBC 报错】Connections could not be acquired from the underlying database!

项目启动报错:    1 [2016-07-13 10:04:15,074] ERROR org.apache.ibatis.executor.BaseExecutor Could not get a databaseId from dataSource 2 java.sql.SQLException: Connections co......

angel挤一挤 ⋅ 2016/07/13 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Centos7重置Mysql 8.0.1 root 密码

问题产生背景: 安装完 最新版的 mysql8.0.1后忘记了密码,向重置root密码;找了网上好多资料都不尽相同,根据自己的问题总结如下: 第一步:修改配置文件免密码登录mysql vim /etc/my.cnf 1...

豆花饭烧土豆 ⋅ 37分钟前 ⋅ 0

熊掌号收录比例对于网站原创数据排名的影响[图]

从去年下半年开始,我在写博客了,因为我觉得业余写写博客也还是很不错的,但是从2017年下半年开始,百度已经推出了原创保护功能和熊掌号平台,为此,我也提交了不少以前的老数据,而这些历史...

原创小博客 ⋅ 今天 ⋅ 0

LVM讲解、磁盘故障小案例

LVM LVM就是动态卷管理,可以将多个硬盘和硬盘分区做成一个逻辑卷,并把这个逻辑卷作为一个整体来统一管理,动态对分区进行扩缩空间大小,安全快捷方便管理。 1.新建分区,更改类型为8e 即L...

蛋黄Yolks ⋅ 今天 ⋅ 0

Hadoop Yarn调度器的选择和使用

一、引言 Yarn在Hadoop的生态系统中担任了资源管理和任务调度的角色。在讨论其构造器之前先简单了解一下Yarn的架构。 上图是Yarn的基本架构,其中ResourceManager是整个架构的核心组件,它负...

p柯西 ⋅ 今天 ⋅ 0

uWSGI + Django @ Ubuntu

创建 Django App Project 创建后, 可以看到路径下有一个wsgi.py的问题 uWSGI运行 直接命令行运行 利用如下命令, 可直接访问 uwsgi --http :8080 --wsgi-file dj/wsgi.py 配置文件 & 运行 [u...

袁祾 ⋅ 今天 ⋅ 0

JVM堆的理解

在JVM中,我们经常提到的就是堆了,堆确实很重要,其实,除了堆之外,还有几个重要的模块,看下图: 大 多数情况下,我们并不需要关心JVM的底层,但是如果了解它的话,对于我们系统调优是非常...

不羁之后 ⋅ 昨天 ⋅ 0

推荐:并发情况下:Java HashMap 形成死循环的原因

在淘宝内网里看到同事发了贴说了一个CPU被100%的线上故障,并且这个事发生了很多次,原因是在Java语言在并发情况下使用HashMap造成Race Condition,从而导致死循环。这个事情我4、5年前也经历...

码代码的小司机 ⋅ 昨天 ⋅ 2

聊聊spring cloud gateway的RetryGatewayFilter

序 本文主要研究一下spring cloud gateway的RetryGatewayFilter GatewayAutoConfiguration spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/config/G......

go4it ⋅ 昨天 ⋅ 0

创建新用户和授予MySQL中的权限教程

导读 MySQL是一个开源数据库管理软件,可帮助用户存储,组织和以后检索数据。 它有多种选项来授予特定用户在表和数据库中的细微的权限 - 本教程将简要介绍一些选项。 如何创建新用户 在MySQL...

问题终结者 ⋅ 昨天 ⋅ 0

android -------- 颜色的半透明效果配置

最近有朋友问我 Android 背景颜色的半透明效果配置,我网上看资料,总结了一下, 开发中也是常常遇到的,所以来写篇博客 常用的颜色值格式有: RGB ARGB RRGGBB AARRGGBB 这4种 透明度 透明度...

切切歆语 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部