预防classloader内存泄漏

本文探讨了Classloader内存泄漏的问题,特别是在使用动态部署功能时如何避免OOM错误。文章通过一个简单的例子解释了内存泄漏的发生机制,并提到了在使用OSGi等技术时可能遇到的相关问题。此外,还提供了使用Eclipse MAT进行内存分析的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在开发一个插件动态部署功能,由于在单元测试里批量进行了redeploy,竟然到最后出现了OOM, faint。
看来有必要回顾一下classloader memory leak。

Classloader的内存泄漏。早在JDK1.5以前,就频繁出现于tomcat, jboss的redeploy动作后。
限于当时没有一款像样的内存泄漏分析工具问世。导致,很多用户都不敢轻易使用hotdeploy功能。

随着JDK6的发布,动态化,OSGi等概念也如火如荼地大规模应用于各大app server。使得classloader内存泄漏的问题,再次引起人们的注意。

所谓的classloader内存泄漏,举个简单例子说明一下。
假设有A和B两个classloader,分别加载 A 和 B两个类。
他们new出来的instance,取名叫 a 和 b。此时,如果你通过某种方式,将a的instance传递给b,b又不小心hold住a的实例时,就有可能发生memory leak。
仔细分析,主要是因为a实例hold class A , class A hold classloader A,b hold a,那么b也就跟classload A有了间接引用关系。
GC过程中,如果发现classloader a 从classloader b的引用关系可达(reached),那么classloader A是不会被回收。

这是一个classloader的小常识,多数人都能很好理解。但问题就在于实际应用过程中,classloader的复杂性,往往会让你神不知鬼不觉地跌入memory leak的陷阱。
比如OSGi,你可能会将一些公用的class或lib放到 Share Bundle, 这个bundle是你不希望会被undeploy或很少undeploy的。
不幸的是,随着系统功能逐渐的丰富起来,业务bundle A的某个实例可能稀里糊涂地被 Share bundle hold住了,此时,你又在毫不知情地情况下,尝试了多次redeploy,那memory leak跟你相见只是时间问题。

对于一般应用,我们不需要关注得太深入。但如果你的系统经常使用一些动态化功能,或许就该体检一下了。

一般推荐使用Eclipse MAT做内存分析,从root开始往下找你期望被unloaded的classloader,并祈祷它不要被找到。

推荐下面三篇文档:

http://blogs.sun.com/fkieviet/entry/classloader_leaks_the_dreaded_java
http://blogs.sun.com/fkieviet/entry/how_to_fix_the_dreaded
http://www.zeroturnaround.com/blog/rjc201/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值