Details

    • Steps to Reproduce:
      Hide

      See attached test application

      Show
      See attached test application

      Description

      Hi,
      a memory leak appears in Drools if a StatefulKnowledgeSession is created without a transaction manager being speciifed (despite the fact that the dispose method is called for each session, be it created or loaded).

      To be more clear, this is the code that creates the session:

      Environment env = KnowledgeBaseFactory.newEnvironment();
      env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, emf);
      return JPAKnowledgeService.newStatefulKnowledgeSession(readKnowledgeBase(), null, env);

      When analyzing the memory dumps of a Spring-based webapplication that uses JBPM, under stress conditions, the Eclipse Memory Analyzer blames org.drools.persistence.SingleSessionCommandService class as the main cause of the leakage. This class is taking up to the 46% of the whole heap by accumulating instances of java.lang.Object[] arrays. These arrays are actually elements of a synchronized map called sysnchronizations (see SingleSessionCommandService.java, line 73).

      For my understanding of the source code of Drools, the sysnchronizations map is filled every time the registerRollbackSync method of SingleSessionCommandService is called; on the other hand, its elements are removed only if a JtaTransactionSynchronizationAdapter is successfully registered against the transaction (via javax.transaction.Transaction.registerSynchronization method).
      If I understand it correctly, this happens only if a javax.transaction.TransactionManager object is specified in the environment properties or one is found by JtaTransactionManager.findTransactionManager.

      When no transaction manager is present (or none is found by findTransactionManager), method SynchronizationImpl.afterCompletion (the only one eligible to remove elements from SingleSessionCommandService.synchronizations) is never called and memory increases with each new session.

      Please note that if no transaction synchronization manager is passed as an environement property, then org.drools.persistence.jta.JtaTransactionManager never finds it, even if the JNDI lookup successfully retrieves it; method findTransactionSynchronizationRegistry never sets the tsr attribute, hence if it was null at the time the method is called, so it is when it returns.

      I also tried to set the transaction manager but I still get a constant memory consumption. The Eclipse Memory Analyzer claims that, in this case, class org.drools.reteoo.ReteooStatefulSession is suspected for the leakage.

      As a final note, there's a minor issue in class JtaTransactionSynchronizationAdapter: at line 31, the afterCompletion method is called on object this rather than on object ts (TransactionSynchronization). This could cause a loop if status is STATUS_ACTIVE.

      I'm working on a test case to reproduce the memory issues. I will provide one as soon as possible along with a heap dump.

      Fabio

        Gliffy Diagrams

          Attachments

            Issue Links

              Activity

                People

                • Assignee:
                  mark.proctor Mark Proctor
                  Reporter:
                  f.strozzi Fabio Strozzi
                • Votes:
                  0 Vote for this issue
                  Watchers:
                  3 Start watching this issue

                  Dates

                  • Created:
                    Updated: