问题
在服务器运行过程中,Spring不停的运行计划任务和OpenSessionInViewFilter
,使得Tomcat反复加载对象而产生框架并用时可能产生的内存泄漏,则使用IntrospectorCleanupListener
作为相应的解决办法。
解决方式
Spring中的提供一个名为org.springframework.web.util.IntrospectorCleanupListener
的监听器。它主要负责处理由JavaBeans Introspector(内省对象)的使用而引起的内存泄露。
Spring中的描述
它是一个在web应用关闭的时候,清除JavaBeans Introspector的监听器。web.xml中注册这个listener
。可以保证在web应用关闭的时候释放与掉这个web应用相关的class loader和由它管理的类。如果使用JavaBeans Introspector来分析应用中的类,Introspector
中会保留这些类的引用。结果在应用关闭的时候,这些类以及web应用相关的class loader没有被垃圾回收。
不幸的是,清除Introspector
的唯一方式是刷新整个缓存。这是因为没法判断哪些是属于应用的引用。所以删除被缓存的introspection
会导致把这台电脑上的所有应用的introspection
都删掉。需要注意的是,Spring托管的bean不需要使用这个监听器。因为Spring它自己的introspection
所使用的缓存在分析完一个类之后会被马上从Java Beans Introspector缓存中清除掉。应用程序中的类从来不直接使用Java Beans Introspector。所以一般不会导致内部查看资源泄露。但是一些类库和框架往往会产生这个问题。
例如Struts和Quartz,单个的内部查看泄漏会导致整个的web应用的类加载器不能进行垃圾回收。在web应用关闭之后,会看到此应用的所有静态类资源。这个错误当然不是由这个类自身引起的。
用法很简单,就是在web.xml中加入:1
2
3<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>
Servlet标准不允许在web容器内自行做线程管理,Quartz的问题确实存在。
对于web容器来说,最忌讳应用程序私自启动线程,自行进行线程调度,像Quartz这种在web容器内部默认就自己启动10线程进行异步job调度的框架本身就是很危险的事情,很容易造成Servlet线程资源回收不掉。