b.Jre Memory Leak Prevention Listener

本文我们来分析分析应用服务器的内存泄露的问题,看看Tomcat是如何应对这个问题的;

首先,来看看内存泄露这个词,内存对于java程序来说,即指JVM内存,而我们知道JVM的内存泄露是有很多种情况的;
一种情况,class泄露是perm区的内存,此种场景就是当应用服务器的类特别多的时候,perm区的容量也是由限度的,会撑爆;
另外一种就是,java对象太多,新生代,老年代等对象存储区太多,full GC都已经收拾不了这种残局;
上述的两种情况,最终都会导致OOM溢出;
而作为Tomcat来讲,如何避免这种溢出,就是这个 Jre Memory Leak Prevention Listener 的能力了;

对于第一种class的情况, Jre Memory Leak Prevention Listener将class的加载优先放在系统类加载器这一级中,来解决这个问题;
回过头来,我们先看看Tomcat的class层级结构就可以明白:

作为每一个应用的WebappClassLoader,如果要加载同样的类库和class,相当于每一份ClassLoader中都得加载一遍,而无论是哪来的 ClassLoader,只要再同一个JVm下,都会占用perm区的资源;
如果每个应用中的加载的类库版本不同还好说,或者加载的库千差万别也好说,那么每一个 WebappClassLoader都加载一遍这些Class没有其他的办法;
而一般如log4j,sax-dom的xml解析,jdbc驱动等等这些非常常用的类库,很多应用都一样;
因此,我们一般在开发应用的时候,技术经理总会说,有没有什么通用的库和lib包,都要放到common目录下面就是这个道理;

Jre Memory Leak Prevention Listener和上述的思路类似,其主要会将一些常用的class资源泄露的库优先加载;
如下面的一段代码:

classToInitialize属性是以,分隔的一串字符串的配置,实际的意思就是预先加载的一系列的类;
你可以在 Jre Memory Leak Prevention Listener中进行配置,然后优先在系统ClassLoader中进行加载;

说到这里,Jre Memory Leak Prevention Listener的整体流程是先保存原来的线程上下文的classloader,然后直接进行切换,最后再切换回来:


对于第二种情况,也就是内存泄露是不是因为class的问题,而是因为java对象太多造成的;
其实也可以借鉴class的处理办法,即很多库,特别是java的库中,JDBC驱动库这种通用库中,例如数据驱动的初始化,如果在应用类加载器中进行初始化,这些都会产生n多个对象,我们不妨将其优先在系统类加载器中加载,这样如果该对象在查找的时候,直接通过双亲委派查找到了系统ClassLoader加载的类,对于类中引用的静态对象资源直接进行初始化,这样应用中的查找到该类的时候,相当于是已经初始化过的类引用的静态资源,这样大大减少了降低java对象的作用,使其只有一份;
如DriverManager的启动:

如果是应用类加载器进行加载,不同应用中可能将其注册的驱动实现类加载到自己的应用类加载器中,并进行初始化,类的增多暂且不说,这一系列的操作会搞出很多对象出来;
而通过这种“预热”的机制,一下子就把所有的驱动进行初始化了,而在应用中无非也是这么调用API,所以这样就相当于减少了n多个对象的创建;

类似的机制还有很多, Jre Memory Leak Prevention Listener还可以减少一些线程创建,其思路也是也是这种将每一个应用的线程变成只有一份线程;
我们来看看配置:
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值