12 Replies Latest reply on Jun 12, 2018 4:47 AM by Ondra Chaloupka

    Memory Leak in JBossLocalTransactionProvider

    Anthony Durussel Newbie



      We have analyzed a case where two Jboss server are implicated in a remote EJB transaction.


      The scenario is the following :


      Java standalone client -------(EJB CALL on server 1)------>   Server 1 start transaction, enlist XA ressource  and call server 2 ------(EJB CALL to server 2)------->   Server 2 enlist subordinate transaction and return


      The scenario works as expected and the XA transaction is committed correctly. However on Server 2 the subordinate transaction is stored at two levels:


      1. inside a Map (named known) in Class org.wildfly.transaction.client.provider.jboss.JBossLocalTransactionProvider.java during call to method findOrImportTransaction.


           final class XAImporterImpl implements XAImporter {

              public ImportResult<Transaction> findOrImportTransaction(final Xid xid, final int timeout, final boolean doNotImport) throws XAException {

                  try {

                      final SimpleXid simpleXid = SimpleXid.of(xid);

                      final SimpleXid gtid = simpleXid.withoutBranch();

                      final ConcurrentMap<SimpleXid, Entry> known = JBossLocalTransactionProvider.this.known;

                      Entry entry = known.get(gtid);

                      if (entry != null) {

                          return new ImportResult<Transaction>(entry.getTransaction(), entry, false);


                      final boolean imported;

                      Transaction transaction;

                      if (doNotImport) {

                          imported = false;

                          transaction = ext.getTransaction(xid);



                          if (transaction == null) {

                              return null;


                      } else {

                          final TransactionImportResult result = ext.importTransaction(xid, timeout);

                          transaction = result.getTransaction();

                          imported = result.isNewImportedTransaction();


                      entry = getEntryFor(transaction, gtid);

                     final Entry appearing = known.putIfAbsent(gtid, entry);

                      if (appearing != null) {

                          // even if someone else beat us to the map, we still might have imported first... preserve the original Entry for economy though

                          return new ImportResult<Transaction>(transaction, appearing, imported);

                      } else {

                          return new ImportResult<Transaction>(transaction, entry, imported);


                  } catch (XAException e) {

                      throw e;

                  } catch (Throwable t) {

                      throw Log.log.resourceManagerErrorXa(XAException.XAER_RMFAIL, t);





      2. inside another Map (named _transaction) in Class  com.arjuna.ats.internal.jta.transaction.arjunacore.jca.TransactionImporterImple.java  during call to method  importTransaction of class org.jboss.tm.ExtendedJBossXATerminator (see above).


      When the transaction is commited references to this subordinate transaction are kept in both Map detailed above.

      A mechanism of cleanup based on timeout is implemented to remove old transaction in the Map (named known) in class org.wildfly.transaction.client.provider.jboss.JBossLocalTransactionProvider.java

      but the  map (named _transaction) is never clean up. This leads to a memory leak if server is never restarted.


      To my understanding, it seems that at the commit phase of this subordinate transaction, we should call the removeImportedTransaction method of interface ExtendedJBossXATerminator to remove the subordinate transaction from the map.


      Can somebody confirm this analyze ?


      Thanks in advance for your time.