Ehcache - 使用复制时PermGen内存泄漏

时间:2014-04-02 10:23:44

标签: hibernate memory-leaks classloader ehcache permgen

我使用Ehcache作为Hibernate二级缓存的提供者。没有复制,一切正常,但是当我添加复制时,我在Tomcat 7上重新部署时会遇到类加载器内存泄漏。

首先,我尝试使用以下ehcache.xml进行RMI复制:

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">

    <cacheManagerPeerProviderFactory
        class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
        properties="peerDiscovery=automatic, multicastGroupAddress=230.0.0.1, multicastGroupPort=4446"/>

    <cacheManagerPeerListenerFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"/>

    <defaultCache maxElementsInMemory="10">
        <cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"/>
    </defaultCache>

</ehcache>

我注意到经过一些重新部署后,我得到了PermGen的内存错误。我使用VisualVM找到根本原因。这是从root开始的路径:

this     - value: org.apache.catalina.loader.WebappClassLoader #2
 <- <classLoader>     - class: net.sf.ehcache.distribution.ConfigurableRMIClientSocketFactory, value: org.apache.catalina.loader.WebappClassLoader #2
  <- <class>     - class: net.sf.ehcache.distribution.ConfigurableRMIClientSocketFactory, value: net.sf.ehcache.distribution.ConfigurableRMIClientSocketFactory class ConfigurableRMIClientSocketFactory
   <- csf     - class: sun.rmi.transport.tcp.TCPEndpoint, value: net.sf.ehcache.distribution.ConfigurableRMIClientSocketFactory #1
    <- key     - class: java.util.HashMap$Entry, value: sun.rmi.transport.tcp.TCPEndpoint #5
     <- [12]     - class: java.util.HashMap$Entry[], value: java.util.HashMap$Entry #12867
      <- table     - class: java.util.HashMap, value: java.util.HashMap$Entry[] #1002 (16 items)
       <- localEndpoints (sticky class)     - class: sun.rmi.transport.tcp.TCPEndpoint, value: java.util.HashMap #1192

然后我决定尝试JGroups而不是RMI:

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">

    <cacheManagerPeerProviderFactory class="net.sf.ehcache.distribution.jgroups.JGroupsCacheManagerPeerProviderFactory"/>

    <defaultCache maxElementsInMemory="10">
        <cacheEventListenerFactory class="net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory"/>
    </defaultCache>

</ehcache>

但最终遇到了同样的问题!

this     - value: org.apache.catalina.loader.WebappClassLoader #2
 <- <classLoader>     - class: org.jgroups.protocols.TP$1, value: org.apache.catalina.loader.WebappClassLoader #2
  <- <class>     - class: org.jgroups.protocols.TP$1, value: org.jgroups.protocols.TP$1 class TP$1
   <- [0]     - class: java.lang.ThreadGroup[], value: org.jgroups.protocols.TP$1 #1
    <- groups     - class: java.lang.ThreadGroup, value: java.lang.ThreadGroup[] #2 (4 items)
     <- group (thread object)     - class: java.lang.Thread, value: java.lang.ThreadGroup #1

正如您所看到的,使用JGroups的原因是不同的,但结果是相同的--OutOfMemoryError:PermGen空间。

我已尝试将Ehcache移至Tomcat lib目录并将net.sf.ehcache.constructs.web.ShutdownListener添加到web.xml,但它没有帮助。

我正在使用ehcache-core 2.6.8和ehcache-jgroupsreplication 1.7。

1 个答案:

答案 0 :(得分:3)

RMI的问题似乎是由与此JDK-8025071类似的错误引起的,显然没有办法在关机时清除hashmap,因此没有解决方法。

JGroups的问题似乎是JGRP-1576。使用此leak preventor可以解决此问题。所以我会说,如果关闭tomcat进程并重新启动不是一个选项,带防漏的JGroups是你最好的选择。

这样做与重新部署大致相同,并解决了在项目中升级库时未来可能出现的这些问题和其他问题。