开发环境中,一直使用热部署;
当重新编译的时候,有些资源不能够释放,从而占用了内存;多热部署几次就内存溢出了。
今天解决了这几个问题;
在实际项目中,主要是这几类资源无法释放:
1,连接池
2,自己写的任务队列线程,
3,mysql的线程;
爆出的warning大概是:
[MySQL S tatement Cancellation Timer] but has failed to stop it. This is very likely to c reate a memory leak.
类似的问题应该是都是资源无法释放;
那我们就从这里入手:
1,释放连接池不能释放的资源:
1)如果你用的是common-dbcp 可以参考这个:
https://issues.apache.org/jira/browse/DBCP-332
2)如果是连接池,可以开启一个context的监听器:
public class ContextDestroyedListener implements ServletContextListener {
@Override
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("you must be reload tomcat....please waiting ...");
CacheManager.shutdown();
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
try {
DriverManager.deregisterDriver(driver);
System.out.println("stoping.... "+driver.toString());
} catch (SQLException e) {
e.printStackTrace();
}
}
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
Thread[] threadArray = threadSet.toArray(new Thread[threadSet.size()]);
for(Thread t:threadArray) {
if(t.getName().contains("Abandoned connection cleanup thread")||t.getName().contains("task_excutor")) {
synchronized(t) {
t.stop();
}
}
}
}
@Override
public void contextInitialized(ServletContextEvent arg0) {
}
}
需要在web.xml里面配置监听。
还有需要特别注意的是:mysql驱动lib包尽量放在tomcat/lib下,因为这个驱动tomcat是可以共用的,当然,如果你只有一个应用,那就没有这个问题了。
3)如果是自己的线程无法释放资源:
我的处理器比较弱:
TaskExcutor te=new TaskExcutor();
Thread t = new Thread(te);
t.setName("task_excutor_thread_0");
t.start();
可以使用线程名称来关闭:
if(t.getName().contains("Abandoned connection cleanup thread")||t.getName().contains("task_excutor")) {
synchronized(t) {
t.stop();
}
}
可能你会遇到这个异常:
Exception in thread "task_excutor_thread_0" java.lang.IllegalMonitorStateExcepti
on
at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLoc
k.java:155)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(Abstrac
tQueuedSynchronizer.java:1260)
at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:46
0)
at java.util.concurrent.LinkedBlockingDeque.takeFirst(LinkedBlockingDequ
e.java:492)
at java.util.concurrent.LinkedBlockingDeque.take(LinkedBlockingDeque.jav
a:678)
at com.cms.cache.TaskQueue.pull(TaskQueue.java:48)
at com.cms.cache.TaskExcutor.run(TaskExcutor.java:8)
at java.lang.Thread.run(Thread.java:745)
可能是应该没有用到线程锁的原因;具体原因是因为我没用到线程锁。