Atomikos Forum

NonXA statement tracking causes out of memory error with TX

I read about this posted before in some for or another. But if you start a transaction and create lots of sql statements and even though you close them ,atomikos statement tracking will cause an out of memory error. We have the same code running with JBoss JTA and it doesn't fail on memory. It doesn't look like there is a way to fix this without code changes. It seem that if the caller code calls statement.close() that AtomikosThreadLocalConnection should remove it from its statement collection tracking. No need to track it if developer called close already. This testcase seems extreme but if your sql statements and # columns are larger, it fails with less statements. Is this fixed in paid version already?

Using: transactions-osgi-3.9.3.jar.

Run with these memory parameters on startup.
// -Xmx512M -Xms384M with TX fails somewhere after 770000/820000
// doesn't fail if useTx = false;

Here is some example code:
public static void main(String[] args)
{
  boolean useTx = true;

  com.atomikos.icatch.jta.UserTransactionImp imp = new com.atomikos.icatch.jta.UserTransactionImp();
  com.atomikos.icatch.jta.UserTransactionManager tm = new com.atomikos.icatch.jta.UserTransactionManager();

  AtomikosNonXADataSourceBean ds = new AtomikosNonXADataSourceBean();
  ds.setUniqueResourceName("testds");
  ds.setDriverClassName("net.sourceforge.jtds.jdbc.Driver");
  ds.setUrl("jdbc:jtds:sqlserver://localhost:1433/XNET");
  ds.setUser("sa");
  ds.setPassword("password");
  ds.setPoolSize(3);

  if (useTx)
  {
      try
      {
          tm.begin();
      }
      catch (Exception e)
      {
          e.printStackTrace();
      }
  }

  for (int cc = 0; cc < Integer.MAX_VALUE; cc++)
  {
      if ((cc % 10000) == 0)
      {
          System.out.println(cc);
      }

      String sql = "SELECT " +
              cc;
      Connection conn = null;
      PreparedStatement stmt = null;

      try
      {
          conn = ds.getConnection();
          stmt = conn.prepareStatement(sql);

          stmt.executeQuery();
      }
      catch (SQLException ex)
      {
          ex.printStackTrace();
      }
      finally
      {
          try
          {
              if (stmt != null)
                  stmt.close();
              if (conn != null)
                  conn.close();
          }
          catch (Exception ex)
          {

          }
      }

  }

  if (useTx)
  {
      try
      {
          tm.commit();
      }
      catch (Exception e)
      {
          e.printStackTrace();
      }
  }

  System.out.println("Done");
}
John Landers Send private email
Tuesday, May 19, 2015
 
 
Hi,

Thanks for the feedback. This is not fixed in the commercial version but we can fix it can be fixed if need be...
Guy Pardon Send private email
Tuesday, May 19, 2015
 
 
Since we close all our statements. This list of non closed statements is small.

I would think a proxy around a statement would be best fix
but a quick workaround was to add iterator to remove closed connections to: AbstractConnectionProxy

    protected synchronized void addStatement(Statement s)
    {
        // if you always close statements this list should be really small.
        for (Iterator iter = statements.iterator(); iter.hasNext();)
        {
            try
            {
                Statement stmt = (Statement) iter.next();

                if (stmt.isClosed())
                {
                    iter.remove();
                }
            }
            catch (Exception ex)
            {

            }
        }

        /* 51 */statements.add(s);
    }
John Landers Send private email
Wednesday, May 20, 2015
 
 
Thanks for sharing!

I scheduled a fix for the upcoming release.
Guy Pardon Send private email
Wednesday, May 20, 2015
 
 

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

Other recent topics Other recent topics