我使用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。
答案 0 :(得分:3)
RMI的问题似乎是由与此JDK-8025071类似的错误引起的,显然没有办法在关机时清除hashmap,因此没有解决方法。
JGroups的问题似乎是JGRP-1576。使用此leak preventor可以解决此问题。所以我会说,如果关闭tomcat进程并重新启动不是一个选项,带防漏的JGroups是你最好的选择。
这样做与重新部署大致相同,并解决了在项目中升级库时未来可能出现的这些问题和其他问题。