2 Replies Latest reply on Jan 10, 2012 9:13 AM by daniell

    Memory Leak when calling @Destroy (with SFSBs)

    daniell

      Hi!


      I've discovered a memory leak in our application and I think it is a bug in Seam. Here we go:


      We're using Seam 2.2.2.Final deployed in an EAR on JBoss AS 5.1.0.GA.


      In an example-project, we have 2 Seam components, one POJO and one SFSB. The POJO-component uses the SFSB-component via Seam-DI (@In). The POJO-component has a method annotated with @Destroy.


      We are using the POJO-component in a (long-running-)conversation. Thus, the TestComponentA as well as the TestEJB will be created.
      When the conversation is ended and all components will be removed, the @Destroy-methods of all seam-components are called one after each other. The order, the @Destroy-methods are called, depend on the hashCode of the seam-name of the components (the component-names are put into an java.util.HashSet in the method org.jboss.seam.contexts.ServerConversationContext.getNamesFromSession() - the for-loop of the method org.jboss.seam.contexts.Contexts.destroy iterates over this HashSet afterwards).


      In the following example, the component-names have been chosen in this way, that the TestEJB will be removed before the TestComponentA is removed. So see the call-sequence:



      1. the SFSB-component is destroyed by seam - the container removes the SFSB

      2. the @Destroy-method of the POJO-component is called. But before, Seam-DI creates a new SFSB-component TestEJB because of the @In-annotation

      3. the POJO-component is removed by the GC

      4. the SFSB-component is still present



      It is easy to see that there are unused SFSBs via the jmx-console or in the server-log:


      10:56:31,693 ERROR [STDERR] TestEJB.postConstruct() called
      10:56:31,693 ERROR [STDERR] tca created
      [...]
      10:59:36,518 ERROR [STDERR] TestEJB.discard() called
      10:59:36,518 ERROR [STDERR] TestEJB.preDestroy() called
      10:59:36,519 ERROR [STDERR] TestEJB.postConstruct() called
      10:59:36,519 ERROR [STDERR] tca destroyed
      



      To reproduce the bug, 2 simple Components have been created. This is the SFSB-Component:


      @Stateful
      @Name(TestEJB.SEAM_NAME)
      @Interceptors(SeamInterceptor.class)
      @JndiName(TestEJBLocal.JNDI_NAME)
      @Scope(ScopeType.CONVERSATION)
      @AutoCreate
      public class TestEJB implements TestEJBLocal
      {
          public static final String SEAM_NAME = "tcb";
          
          @Remove
          public void discard()
          {
              System.err.println("TestEJB.discard() called");
          }
      
          @PostConstruct
          public void postConstruct()
          {
              System.err.println("TestEJB.postConstruct() called");
          }
      
          @PreDestroy
          protected void preDestroy()
          {
              System.err.println("TestEJB.preDestroy() called");
          }
      }
      


      ...and it's local-interface:


      @Local
      public interface TestEJBLocal
      {
          /** The local JNDI name for this EJB. */
          final static String JNDI_NAME = "ejb/project/TestEJB/local";
          
          public void discard();
      }
      


      Last but not least the POJO-Component:


      @Scope(ScopeType.CONVERSATION)
      @Name(TestComponentA.SEAM_NAME)
      @AutoCreate
      public class TestComponentA implements Serializable
      {
          public static final String SEAM_NAME = "tcd";
          private static final long serialVersionUID = 7550180731244593255L;
      
          @In(value=TestEJB.SEAM_NAME)
          private TestEJBLocal testEJB;
      
          @Create
          public void create() {
              System.err.println("tca created");
          }
      
          @Destroy
          public void destroy() {
              System.err.println("tca destroyed");
          }
      }