JBoss Weld + java.lang.OutOfMemoryError: PermGen空间

13

我刚刚开始使用Weld来利用CDI JSF 2 Beans + conversation scope。

这是我的Maven依赖项:

    <dependency>
        <groupId>org.jboss.weld.servlet</groupId>
        <artifactId>weld-servlet</artifactId>
        <version>1.0.1-Final</version>
        <type>jar</type>
        <scope>compile</scope>
    </dependency>

这是我 web.xml 文件中的条目:

<listener>
  <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
</listener>

我立即注意到的一件事是,我只需要重新加载我的Tomcat 7大约2次,java.lang.OutOfMemoryError:PermGen space就会出现在catalina.out日志文件中。

在使用Weld之前,我可以安全地重新加载我的Tomcat 7超过10次,而不会出现java.lang.OutOfMemoryError。我认为在catalina.sh中增加Xmx选项会有所帮助,但在我的经验中并没有。 JAVA_OPTS=-Xmx1024m

这是正常现象吗?


1
这绝对不是正常现象。但除非你在代码中进行一些挖掘并找到消耗内存的部分,否则无法确定是你的代码还是实现本身的问题... - Jan Groth
@jan groth:我认为这不是我的代码问题,因为这只是一个非常简单的测试项目,例如一个带有计数器的JSF Bean等。在使用Weld之前,我使用的是Spring或默认的JSF托管Bean,它们都很好。 - Bertie
JAVA_OPTS=-Xmx1024m 不会增加 Permgen。而 -XX:MaxPermSize=256m 会增加。 - Ondra Žižka
3个回答

5

当你想使用简单的servlet容器来实现Java EE时,这确实是一个非常典型的错误;)

不过,开玩笑的。Tomcat默认的permgen设置只有64MB。其中包括类定义(即当您执行Class#forName()时获得的内容)。粗略地说,Weld扫描类路径中的每个JAR和类以查找注释,以便可以编程方式创建连接配置的内存映射(在使用注释之前,通常通过XML文件实现)。但是,将许多类放入类路径并加载那么多类会在permgen空间中留下很少的空间以用于Tomcat的热部署。

有几种方法可以解决这个问题。最合理的方法是增加permgen空间。您可以将其设置为VM参数。 256MB是一个好的开始。

-XX:MaxPermSize=256m

如果您在Eclipse中使用Tomcat,则需要通过双击“Servers”视图中的服务器条目,单击“打开启动配置”链接,单击“参数”选项卡,然后将其(以空格分隔)添加到“VM参数”字段中来设置它。
此外,您还可以强制JVM更加节约permgen空间。其中的对象默认情况下很少被卸载。请添加以下VM参数。
-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled

参见:


1
除了增加PermGen之外,您还应该从Weld扫描器中排除不支持Weld的包。请参见此处:

20.1. 排除类的扫描和部署

<?xml version="1.0" encoding="UTF-8"?>
  <beans xmlns="http://java.sun.com/xml/ns/javaee" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xmlns:weld="http://jboss.org/schema/weld/beans" 
         xsi:schemaLocation="
            http://java.sun.com/xml/ns/javaee http://docs.jboss.org/cdi/beans_1_0.xsd
            http://jboss.org/schema/weld/beans http://jboss.org/schema/weld/beans_1_1.xsd">

      <weld:scan>

          <!-- Don't deploy the classes for the swing app! -->
          <weld:exclude name="com.acme.swing.**" />

          <!-- Don't include GWT support if GWT is not installed -->
          <weld:exclude name="com.acme.gwt.**">
              <weld:if-class-available name="!com.google.GWT"/>
          </weld:exclude>

          <!--
              Exclude classes which end in Blether if the system property verbosity is set to low
              i.e.  java ... -Dverbosity=low            
          -->        
          <weld:exclude pattern="^(.*)Blether$">
              <weld:if-system-property name="verbosity" value="low"/>
          </weld:exclude>

         <!--
               Don't include JSF support if Wicket classes are present, and the viewlayer system
               property is not set
          -->
          <weld:exclude name="com.acme.jsf.**">
              <weld:if-class-available name="org.apahce.wicket.Wicket"/>
              <weld:if-system-property name="!viewlayer"/>
          </weld:exclude>
      </weld:scan>

  </beans>

1

尝试设置permsize:-XX:MaxPermSize = 200m。您可能正在加载大量的类定义,从而填满永久生成空间。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接