If I run the program below with
java -Xmx32M RepeatStatement
I will get an OutOfMemory error in the client.
java -Xmx32M RepeatStatement
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at
org.apache.derby.client.am.Cursor.allocateCharBuffer(Cursor.java:1260)
at
org.apache.derby.client.net.NetStatementReply.parseSQLDTARDarray(NetStatementReply.java:1356)
at
org.apache.derby.client.net.NetStatementReply.parseQRYDSC(NetStatementReply.java:1207)
at
org.apache.derby.client.net.NetStatementReply.parseOpenQuery(NetStatementReply.java:479)
at
org.apache.derby.client.net.NetStatementReply.parseOPNQRYreply(NetStatementReply.java:223)
at
org.apache.derby.client.net.NetStatementReply.readOpenQuery(NetStatementReply.java:64)
at
org.apache.derby.client.net.StatementReply.readOpenQuery(StatementReply.java:50)
at
org.apache.derby.client.net.NetStatement.readOpenQuery_(NetStatement.java:153)
at
org.apache.derby.client.am.Statement.readOpenQuery(Statement.java:1396)
at
org.apache.derby.client.am.Statement.flowExecute(Statement.java:2001)
at
org.apache.derby.client.am.Statement.executeQueryX(Statement.java:421)
at
org.apache.derby.client.am.Statement.executeQuery(Statement.java:406)
at RepeatStatement.testInsertAndSelect(RepeatStatement.java:31)
at RepeatStatement.main(RepeatStatement.java:10)
If I close the ResultSet or Statement it does not leak. I seem to
recall there being a leak when ResultSets wern't closed, but only on the
server, DERBY-1104. I think it is a new bug, but I am not 100% sure. I
will file a bug tomorrow unless I hear from someone that it is already
filed.
import java.sql.*;
public class RepeatStatement {
public static void main(String[] args) throws Exception{
Class.forName("org.apache.derby.jdbc.ClientDriver");
String url = "jdbc:derby://localhost/testdb;create=true";
Connection conn = DriverManager.getConnection(url);
for (int i = 1; i < 32000; i++)
testInsertAndSelect(conn);
}
public static void testInsertAndSelect(Connection conn) throws
SQLException
{
Statement s = conn.createStatement();
try {
s.executeUpdate("DROP TABLE TAB");
} catch (SQLException se)
{
//ignore table not found exception
}
s.executeUpdate("CREATE TABLE TAB (col1 varchar(32672))");
PreparedStatement ps = conn.prepareStatement("INSERT INTO TAB
VALUES(?)");
ps.setString(1,"hello");
ps.executeUpdate();
ps.setString(1,"hello");
ps.executeUpdate();
ResultSet rs = s.executeQuery("SELECT * from tab");
// drain the resultset
while (rs.next());
// If I don't explicitly close the resultset or
// statement, we get a leak.
//rs.close();
//s.close();
ps.close();
}
}