"java.lang.OutOfMemoryError: PermGen space" with a twist

There are a lot of posts out there about the "java.lang.OutOfMemoryError: PermGen space" exception. A good description of the problem can be found in Frank Kieviet's blog.
One of the main causes for this error is a classloader not being garbage collected when you undeploy an application. A few days ago I encountered this problem but with a certain twist causing it to become even worse.

It all started with JBoss servers suffering from PermGen bloat which lead eventually to a "java.lang.OutOfMemoryError: PermGen space" exception.
Analyzing a heap dump from one of the servers using jhat we saw a long list of about 2000 $Proxy classes which where the immediate suspects for the situation



After some checking some of these proxies we could determine two things:
  1. They have no instances
  2. They are loaded by instances of JBoss RemotingClassLoader



Some more digging showed that there are 819 instances of the JBoss RemotingClassLoader all of them loading only $Proxy classes. This seemed to be a little odd so we used jmap with the "-permstat" option to look at the current status of one of the servers and what we got was a long list of JBoss RemotingClassLoaders - they where all dead !



OK, we have a list of dead classloaders loading proxy classes this is definitely the cause for the leak, but why?
Back to jhat we checked the reference chains to one of the proxies. The result showed a suspect that may be causing the leak: a static field named "classesToGetAndSetters" in Wicket's PropertyResolver class.



A quick pick into the Wicket source code discovered that classesToGetAndSetters is a map caching getters and setters. The problem is that Class objects are used as keys and that this is an unbounded cache with no eviction policy. Now, as long as you put "regular" (non Proxy) classes into this cache you will only encounter the usual classloader leak problem when unloading the application. This was already taken care by wicket, but we have a different problem.
In our case for each Proxy instance there is also a new $Proxy class filling up this cache. To add more complexity all these proxies where retrieved using JBoss remoting. A new RemotingClassLoader was created each time but never released since the cached $Proxy class is still referencing it.
The solution for such an issue is using a bound cache with some sort of eviction policy or something like google-collections ReferenceMap.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值