深入Spring之十三:【清除内存泄漏】***深入解析

深入理解Spring系列之十三:IntrospectorCleanupListener解析


Introspector作用及影响

在分析IntrospectorCleanupListener之前,先了解一下Introspector。Introspector是JDK中java.beans包下的类,它为目标JavaBean提供了一种了解原类方法、属性和事件的标准方法。通俗的说,就是可以通过Introspector构建一个BeanInfo对象,而这个BeanInfo对象中包含了目标类中的属性、方法和事件的描述信息,然后可以使用这个BeanInfo对象对目标对象进行相关操作。

下面看一个简单的示例会很容易明白。为了简单,Student类中只有一个name属性。




结果输出:Student{name='张三'}

通过查看Introspector.getBeanInfo方法的源码会发现,Introspector在构建一个BeanInfo对象的时候,会将构建的BeanInfo对象和原类缓存到一个Map中,源码如下。


通过上的代码可以得出,Introspector间接持有了BeanInfo的强引用。如果使用Introspector操作了很多类,那么Introspector将间接持有这些BeanInfo的强引用。在发生垃圾收集的时候,检测到这些BeanInfo存在引用链,则这些类和对应的类加载器将不会被垃圾收集器回收,进而导致内存泄漏。所以,为了解决这个问题,在使用Introspector操作完成后,调用Introspector类的flushCaches方法清除缓存。


通过上面的代码会发现,清除的时候是清空了整个缓存,因为没有很好的办法来确定每个缓存是属于哪个应用的,所以清除的时候会清除所有应用的缓存。

IntrospectorCleanupListener解析

上面分析了Introspector的作用和影响,那IntrospectorCleanupListener和Introspector有什么关系呢?
IntrospectorCleanupListener是spring-web jar中的类,源码如下。


IntrospectorCleanupListener实现了ServletContextListener接口,也就是说,在web容器初始化(准确的说是在filters或servlets初始化之前)的时候会执行contextInitialized方法,在ServletContext销毁(准确的说是在filters和servlets销毁之后)的时候会执行contextDestroyed方法。从图中contextDestroyed方法,可以看到在销毁ServletContext的时候调用了Introspector.flushCaches方法,清空了对应缓存。IntrospectorCleanupListener中为什么要这么做?难道是Spring使用Introspector操作后没有清空对应缓存?查看IntrospectorCleanupListener类的源码,会发现有这样一段标注。


大意是说,在使用Spring本身的时候并不需要使用此***,因为Spring自己的内部机制会立即清空对应的缓存。虽然,Spring本身不存在这样的问题,但是如果和其它框架结合使用,而其它框架有这个问题,如Struts、Quartz等,那就需要配置这个***,在销毁ServletContext的时候清空对应缓存。

有一点需要注意的是,像这样一个简单的Introspector内存泄漏将会导致整个应用的类加载器不会被垃圾收集器回收,如果有内存泄漏的问题,可以考虑此因素。

配置IntrospectorCleanupListener

在以往的工作经历中,多次看到在web.xml中将IntrospectorCleanupListener配置成非第一个listener。


其实,看过源码的都知道,官方的表述是必须将此***配置成web.xml中的第一个listener,才能在合适的时间发挥最有效的作用。

原因其实很简单,在Servlet3.0规范之前,***的调用是随机的,而从Servlet3.0开始,***的调用顺序是根据其在web.xml中配置的顺序,并且实现ServletContextListener的***,contextInitialized方法调用顺序是按照在web.xml中配置的顺序正序依次执行,而contextDestroyed方法的调用顺序是按照在web.xml中配置的顺序逆序依次执行。所以,如果IntrospectorCleanupListener被配置成了第一个listener,那么它的contextDestroyed方法将最后一个执行,将发挥最有效的清除作用;而如果不是,那么可能会残留未被清除的缓存。



全部评论

相关推荐

来,说点可能被同行“骂”的大实话。🙊当初接数字马力Offer时,朋友都说:“蚂蚁的“内包”公司?你想清楚啊!”但入职快一年后的今天,我反而对他有了不一样的看法!🔹 是偏见?还是信息差!之前没入职之前外面都在说什么岗位低人一等这类。实际上:这种情况不可至否,不能保证每个团队都是其乐融融。但我在的部门以及我了解的周边同事都还是十分好相处的~和蚂蚁师兄师姐之间也经常开一些小玩笑。总之:身份是蚂蚁公司给的,地位是自己挣的(一个傲娇女孩的自述)。🔹 待遇?玩的就是真实!试用期工资全额发!六点下班跑得快(早9晚6或者早10晚7,动态打卡),公积金顶格交。别听那些画饼的,到手的钱和下班的时间才是真的(都是牛马何必难为牛马)。🔹 能不能学到技术?来了就“后悔”!我们拥有权限直通蚂蚁知识库,技术栈多到学不完。说“学不到东西”的人,来了可能后悔——后悔来晚了(哈哈哈哈,可以不学但是不能没有)!💥 内推地址:https://app.mokahr.com/su/ueoyhg❗我的内推码:NTA6Nvs走我的内推,可以直达业务部门,面试流程更快速,进度可查!今天新放HC,之前挂过也能再战!秋招已经正式开始啦~机会就摆在这,敢不敢来试一试呢?(和我一样,做个勇敢的女孩)
下午吃泡馍:数字马力的薪资一般哇,5年经验的java/测试就给人一万出头,而且刚入职第三天就让人出差,而且是出半年
帮你内推|数字马力 校招
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务