Atomikos Forum

OutOfMemoryError using AtomikosNonXADataSourceBean

Hi,

Using TransactionEssentials 3.7.0.

We are using AtomikosNonXADataSourceBean with SQLServer. There is an operation in our application which runs a large number of sql statements within a single transaction (about 15000). We are currently porting it from WebLogic to Tomcat.

Using VisualVM, I could see that after each transaction there were +15000 instances of SQLServerPreparedStatement in the heap. These instances were only garbage collected after an Atomikos checkpoint.

As noted in the following post, AtomikosThreadLocalConnection keeps a reference to every Statement created while it is proxying the database connection:
default82df.html?community.6.2221.16

If the transaction terminates by rolling back, the Statements are removed from the list and they get garbage collected. However, if the transaction terminates by committing, the Statements are not removed. I find that for each transaction, there is an instance of AtomikosNonXAParticipant with a reference to an AtomikosThreadLocalConnection (also one per transaction). These participants are only dereferenced by the coordinator when the next checkpoint occurs. Lowering the checkpoint interval certainly helps but in my testing, I was seeing an extra 1.7Gb of heap (and +116000 Statements) used after running only 8 of these transactions. I'd have to set the interval really low just to cater for this one operation.

Is this a bug or is there a genuine reason for keeping a reference to these closed Statements for transactions which terminate successfully?

It appears that when using XA, AtomikosConnectionProxy also keeps the list of Statements but that it does call forceCloseAllPendingStatements when the transaction commits. This call removes the statements from the list allowing them to be garbage collected.

I made the following change to AtomikosThreadLocalConnection (added forceCloseAllPendingStatements) and it solved my memory problems:

    private void resetForNextTransaction()
    {
        // MY CHANGE. REMOVES THE STATEMENTS.
        forceCloseAllPendingStatements(false);

        try {
            if (Configuration.isInfoLoggingEnabled())
                Configuration.logInfo(this + ": resetting autoCommit to " + originalAutoCommitState);
            //see case 24567
            wrapped.setAutoCommit(originalAutoCommitState);
        } catch (Exception ex) {
            Configuration.logWarning("Failed to reset original autoCommit state: " + ex.getMessage(), ex);
        }
        setTransaction(null);
        participant = null;

    }

Could you please comment on whether this is a bug and if this is a valid fix.

Many thanks.
Alex Williams Send private email
Wednesday, April 11, 2012
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics