Atomikos Forum |
|
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"); }
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); } |