Bug #5191 PreparedStatement.executeQuery() gives OutOfMemoryError
Submitted: 24 Aug 2004 21:53 Modified: 28 Feb 2011 17:27
Reporter: Niklas Lindholm Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / J Severity:S2 (Serious)
Version:4.1 OS:Linux (Linux)
Assigned to: Mark Matthews CPU Architecture:Any

[24 Aug 2004 21:53] Niklas Lindholm
Description:
I am using MySql 4.1.3-beta with Connector/J nightly build 20040822.

When calling executeQuery() in a PreparedStatement I get java.lang.OutOfMemoryError occasionally.

The call is used in a function that is called from a JSP page using Apache Tomcat. If I reload the page a couple of times I get the error in roughly 50% of the reloads. The other times it is working fine.

I have tried to get a stack trace from the OutOfMemoryError, but there doesn't seem to be one. My code currently looks like this:

            System.out.println("*** 1");
            con = getConnection();
            //st = con.createStatement();
            System.out.println("*** 2");
            ps = con.prepareStatement
                //rs = st.executeQuery
                ("SELECT qc.QuestionId, q.Text " +
                 "FROM Questions q, QuestionsCategories qc " +
                 "WHERE qc.CategoryId = ? " +
                 " AND q.QuestionId = qc.QuestionId");
            System.out.println("*** 3");
            ps.setInt(1, catId);
            System.out.println("*** 4");
            try {
                rs = ps.executeQuery();
            }
            catch(Throwable t) {
                System.out.println("*** Got exception! " + t.getMessage());
                t.printStackTrace(System.out);
                throw new ServletException("Caught throwable", t);
            }
            System.out.println("*** 5");

And the result of stdout is this:

*** 1
*** 2
*** 3
*** 4
*** Got exception! null
java.lang.OutOfMemoryError

How to repeat:
...
[24 Aug 2004 22:35] Mark Matthews
How much memory have you allocated to your JVM?

Does this occur if you turn off server-side prepared statements (i.e. add 'useServerPrepStmts=false') to your JDBC url?
[24 Aug 2004 23:42] Niklas Lindholm
I am using Java 1.4.2_04-b05 and I haven't set any memory options so it should be using defaults. The application is pretty small so the memory is probably not used up..

When setting useServerPrepStmts=false the problem goes away. I then tried setting it to true in the JDBC url and then the problem came back. Finally I changed it to false again and the problem was gone. All of this was without restarting the JVM. I just reloaded the application in Tomcat.
[31 Aug 2004 2:37] Eric Herman
How often when calling preparedStatement.executeQuery() do you get java.lang.OutOfMemoryError? What percentage of the time would you estimate this error occurs?
[2 Sep 2004 9:37] Niklas Lindholm
I have only tried it out with this one query that is in the original report. But with that query I estimate that I got the error roughly 50% of the calls.
[7 Sep 2004 18:03] Eric Herman
Perhaps this is data related. I can't reproduce the error, yet.

First, please look at this test case. Perhaps you can run it in your environment. Do you see the bug when running a test like this one?
    
    /**
     * Tests for BUG#5191 -- PreparedStatement.executeQuery() gives 
     * OutOfMemoryError
     * 
     * @throws Exception if the test fails.
     */
    public void testBug5191() throws Exception {
        PreparedStatement pStmt = null;

        try {
            this.stmt.executeUpdate("DROP TABLE IF EXISTS testBug5191Q");
            this.stmt.executeUpdate("DROP TABLE IF EXISTS testBug5191C");

            this.stmt.executeUpdate("CREATE TABLE testBug5191Q"
                    + "(QuestionId int NOT NULL AUTO_INCREMENT, "
                    + "Text VARCHAR(200), " + "PRIMARY KEY(QuestionId))");

            this.stmt.executeUpdate("CREATE TABLE testBug5191C"
                    + "(CategoryId int, " + "QuestionId int)");

            String[] questions = new String[] { "What is your name?",
                    "What is your quest?",
                    "What is the airspeed velocity of an unladen swollow?",
                    "How many roads must a man walk?", "Where's the tea?", };

            for (int i = 0; i < questions.length; i++) {
                this.stmt.executeUpdate("INSERT INTO testBug5191Q(Text)"
                        + " VALUES (\"" + questions[i] + "\")");
                int catagory = (i < 3) ? 0 : i;

                this.stmt.executeUpdate("INSERT INTO testBug5191C"
                        + "(CategoryId, QuestionId) VALUES (" + catagory + ", "
                        + i + ")");
            }

            pStmt = this.conn.prepareStatement("SELECT qc.QuestionId, q.Text "
                    + "FROM testBug5191Q q, testBug5191C qc "
                    + "WHERE qc.CategoryId = ? "
                    + " AND q.QuestionId = qc.QuestionId");

            int catId = 0;
            for (int i = 0; i < 100; i++) {
                execQueryBug5191(pStmt, catId);
            }

        } finally {
            this.stmt.executeUpdate("DROP TABLE IF EXISTS testBug5191Q");
            this.stmt.executeUpdate("DROP TABLE IF EXISTS testBug5191C");

            if (pStmt != null) {
                pStmt.close();
            }
        }
    }

    private void execQueryBug5191(PreparedStatement pStmt, int catId)
            throws SQLException {
        pStmt.setInt(1, catId);

        rs = pStmt.executeQuery();

        assertTrue(rs.next());
        assertTrue(rs.next());
        // assertTrue(rs.next());

        assertFalse(rs.next());
    }

Next. If this the above test passes, perhaps you could create a test that demonstrates the error and post it. Please include the table creation and data loading in the test. Also you may use the "Files" tab to upload if you wish.
[21 Sep 2004 20:12] Niklas Lindholm
Hi!

Sorry for taking to long to get back on this. I have managed to write a small standalone program that triggers the error. I will upload an archive with three files:

Test3.java - The program
output.txt - The shell output from two runs where the error happens.
magigfaq.dmp - A dump of the database contents produced with mysqldump.

One thing to note is that I didn't manage to trigger the error until I added the "Thread.sleep()" statement at the end of the program.

/Niklas
[21 Sep 2004 20:14] Niklas Lindholm
Files that shows the OutOfMemoryException error

Attachment: mysqlbug.tgz (application/x-gzip, text), 3.74 KiB.