Re: Tricky: java.lang.StackOverflowError due to recursive call in warning messages construction

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance

From: Carb Simien [MSFT] (CarbinoS_at_online.microsoft.com)
Date: 10/08/04

  • Next message: Carb Simien [MSFT]: "RE: JDBC Driver for SQLServer 7"
    Date: Fri, 08 Oct 2004 21:19:56 GMT
    
    

    --------------------
    | From: "Alexandre Delarge" <alexandre.delarge@laposte.net.nospam>
    | Newsgroups: microsoft.public.sqlserver.jdbcdriver
    | Subject: Re: Tricky: java.lang.StackOverflowError due to recursive call
    in warning messages construction
    | Date: Mon, 4 Oct 2004 17:24:10 +0200
    | Organization: Guest of TISCALI - FRANCE
    | Lines: 314
    | Message-ID: <cjrpus$t1d$1@news.tiscali.fr>
    | References: <ch4p05$6qt$1@news.tiscali.fr> <ch6o33$3dl$1@news.tiscali.fr>
    <qn0Pe9$nEHA.3212@cpmsftngxa06.phx.gbl>
    | NNTP-Posting-Host: nat-lan.dev.amadeus.net
    | X-Trace: news.tiscali.fr 1096903453 29741 62.210.124.226 (4 Oct 2004
    15:24:13 GMT)
    | X-Complaints-To: abuse@libertysurf.fr
    | NNTP-Posting-Date: Mon, 4 Oct 2004 15:24:13 +0000 (UTC)
    | X-Priority: 3
    | X-MSMail-Priority: Normal
    | X-Newsreader: Microsoft Outlook Express 6.00.2800.1437
    | X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1441
    | Path:
    cpmsftngxa06.phx.gbl!TK2MSFTNGXA03.phx.gbl!TK2MSFTNGP08.phx.gbl!newsfeed00.s
    ul.t-online.de!t-online.de!fr.ip.ndsoftware.net!proxad.net!news.tiscali.fr!n
    ot-for-mail
    | Xref: cpmsftngxa06.phx.gbl microsoft.public.sqlserver.jdbcdriver:6321
    | X-Tomcat-NG: microsoft.public.sqlserver.jdbcdriver
    |
    | Greetings Carb,
    |
    | Here a sample Java code I run within Eclipse IDE that crashes with 10000
    or
    | 11000 print statements when executed with Sun JVM 1.3.1_11 and MS JDBC
    | driver SP3.
    |
    | This code can either generate a OutOfMemoryError, or a StackOverflowError,
    | regarding your JVM parameters. As our JVM is always executed using
    | the -Xmx192m parameter, the stack gets filled before the heap.
    |
    | I could not make tests with Java 1.4 because our current J2EE application
    | server in production cannot run with it.
    |
    | Before running the program, set the maximum number of statements you think
    | your transaction can hold, then run it by providing the full JDBC URL as
    | first argument.
    |
    | Thanks a lot for your attention, and best regards,
    |
    | Alexandre.
    |
    |
    |
    | ----- BEGIN CODE -----
    | import java.sql.Connection;
    | import java.sql.Driver;
    | import java.sql.SQLWarning;
    | import java.sql.Statement;
    |
    | /**
    | * Issue several thousands of PRINT statements inside one unique
    transaction
    | * till JVM stack gets filled.
    | */
    | public class TestStackOverflowError {
    |
    | /**
    | * We'll start with this number of PRINT statements
    | */
    | private static final int START_NUMBER = 5000;
    |
    | /**
    | * Then increments the PRINT counts with this number till we crash
    | */
    | private static final int INCREMENT_STEP = 1000;
    |
    | /**
    | * We'll stop when reaching this limit
    | */
    | private static final int STOP_NUMBER = 50000;
    |
    | /**
    | * The PRINT statement to repeat several thousands of time
    | */
    | private static final String PRINT_STATEMENT = "PRINT 'Hello world !'\n";
    |
    | /**
    | * SQL code prelude
    | */
    | private static final String SQL_BEGIN = "BEGIN TRANSACTION\n";
    |
    | /**
    | * SQL code closure
    | */
    | private static final String SQL_END = "COMMIT TRANSACTION\n";
    |
    | /**
    | * Main method:
    | * 1- Connects to database
    | * 2- Generates the transaction with thousands of PRINTs statements in
    | memory
    | * 3- Execute the SQL code
    | * 4- Retrieve warnings
    | * 5- Loop from step 2 till we crash
    | */
    | public static void main(String[] args) {
    | System.out.println("Starting...");
    |
    | // Check URL is there
    | if(args.length < 1 || args[0] == null || args[0].length() < 3) {
    | System.out.println("Please provide a JDBC URL to connect to ! (eg:
    |
    'jdbc:microsoft:sqlserver://SERVER_ADDRESS:SERVER_PORT;user=USERNAME;passwor
    | d=PASSWORD;DatabaseName=BASE_NAME')");
    | System.exit(1);
    | }
    |
    | // Init vars
    | String url = args[0];
    | int number = START_NUMBER;
    | Connection connection = null;
    | boolean crash = false;
    |
    | try {
    | // Load driver and connects to DB
    | Class dc =
    Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
    | Driver driverInstance = (Driver) dc.newInstance();
    | connection = driverInstance.connect(url, null);
    | connection.setReadOnly(true);
    |
    | // Loop till we reach fixed limit
    | while(true && (number < STOP_NUMBER)) {
    |
    | // Generate SQL code
    | System.out.println("\nGenerating "+ number +" statements in
    memory...");
    | StringBuffer sb = new StringBuffer(SQL_BEGIN);
    | for (int i = 0; i < number; i++) {
    | sb.append(PRINT_STATEMENT);
    | }
    | sb.append(SQL_END);
    |
    | // Execute
    | System.out.println("Executing code...");
    | connection.clearWarnings();
    | Statement statement = connection.createStatement();
    | statement.execute(sb.toString());
    |
    | // Get warnings
    | System.out.println("Retrieving warning messages...");
    | crash = true;
    | SQLWarning warnings = statement.getWarnings();
    | crash = false;
    | System.out.println("Retrieved all warnings succesfully !");
    |
    | // Increase number of PRINT statements to send
    | number += INCREMENT_STEP;
    | }
    | }
    | catch(Throwable t) {
    | // Print error
    | System.out.println("Caught error: " + t);
    | t.printStackTrace();
    | }
    | finally {
    | // Close DB connection if needed
    | try {
    | if(connection != null && ! connection.isClosed() ) {
    | connection.close();
    | }
    | }
    | catch(Exception ex) {
    | // Silent
    | }
    | }
    |
    | System.out.println("\nEnded with " + (crash?"crash on " + number + "
    | statements processing !":"no errors..."));
    | }
    | }
    |
    | ----- END CODE -----
    |
    |
    |
    |
    |
    | ""Carb Simien [MSFT]"" <CarbinoS@online.microsoft.com> wrote in message
    | news:qn0Pe9$nEHA.3212@cpmsftngxa06.phx.gbl...
    | >
    | > --------------------
    | > | From: "Alexandre Delarge" <alexandre.delarge@laposte.net.nospam>
    | > | Newsgroups: microsoft.public.sqlserver.jdbcdriver
    | > | Subject: Re: Tricky: java.lang.StackOverflowError due to recursive
    call
    | > in warning messages construction
    | > | Date: Thu, 2 Sep 2004 11:10:58 +0200
    | > | Organization: Guest of TISCALI - FRANCE
    | > | Lines: 91
    | > | Message-ID: <ch6o33$3dl$1@news.tiscali.fr>
    | > | References: <ch4p05$6qt$1@news.tiscali.fr>
    | > | NNTP-Posting-Host: 62.210.124.226
    | > | X-Trace: news.tiscali.fr 1094116259 3509 62.210.124.226 (2 Sep 2004
    | > 09:10:59 GMT)
    | > | X-Complaints-To: abuse@libertysurf.fr
    | > | NNTP-Posting-Date: Thu, 2 Sep 2004 09:10:59 +0000 (UTC)
    | > | X-Priority: 3
    | > | X-MSMail-Priority: Normal
    | > | X-Newsreader: Microsoft Outlook Express 6.00.2800.1437
    | > | X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1441
    | > | Path:
    | >
    |
    cpmsftngxa10.phx.gbl!TK2MSFTFEED01.phx.gbl!TK2MSFTNGP08.phx.gbl!news-out.cwi
    | >
    |
    x.com!newsfeed.cwix.com!news.tele.dk!news.tele.dk!small.news.tele.dk!fr.ip.n
    | > dsoftware.net!proxad.net!news.tiscali.fr!not-for-mail
    | > | Xref: cpmsftngxa10.phx.gbl microsoft.public.sqlserver.jdbcdriver:6299
    | > | X-Tomcat-NG: microsoft.public.sqlserver.jdbcdriver
    | > |
    | > | Hello again,
    | > |
    | > |
    | > | A few more information:
    | > | Issuing 7000 PRINT statements is ok, the stack overflow error starts
    | > showing
    | > | when going aroung 8000 PRINTs (don't need to fill a 6Mb sql script
    | then).
    | > |
    | > | The amount of warning messages I'm able to get without an error of
    | course
    | > | depends on my stack's size and state before the driver enters its
    | > recursive
    | > | call, so it might vary a bit.
    | > |
    | > | I'm doing some tests with the open source driver jTDS (see
    | > | http://jtds.sourceforge.net/), which looks promissing. It can go up to
    | > 10000
    | > | warnings without problem for it does not use a recursive loop, so of
    | > course
    | > | this helps.
    | > | But I don't think the company I'm working for will agree relying on
    this
    | > | driver. :/
    | > |
    | > | Any feedback from a Microsoft support employee would be nice ;)
    | > |
    | > |
    | > | Regards,
    | > |
    | > | Alexandre Delarge.
    | > |
    | > |
    | > | "Alexandre Delarge" <alexandre.delarge@laposte.net.nospam> wrote in
    | > message
    | > | news:ch4p05$6qt$1@news.tiscali.fr...
    | > | > Greetings to readers,
    | > | >
    | > | >
    | > | > I got this problem with both SP2 and SP3 of the JDBC driver for SQL
    | > Server
    | > | > 2000:
    | > | >
    | > | > The recursive call made in method
    | > | > "com.microsoft.jdbc.base.BaseWarnings.createSQLWarning()" causes a
    | > | > java.lang.StackOverFlowError when number of warning messages (or
    PRINT
    | > sql
    | > | > statements is too important).
    | > | >
    | > | > To reproduce this problem, create a sql script which contains
    | > | approximately
    | > | > 5 megabytes of PRINT statements within one unique transaction, e.g:
    | > | >
    | > | > -----
    | > | > SET NOCOUNT ON
    | > | > PRINT 'Begin'
    | > | > BEGIN TRANSACTION
    | > | > PRINT 'Hello !' -- repeat this statement the required number
    times
    | > to
    | > | > reach a file size of 5mb
    | > | > COMMIT TRANSACTION
    | > | > -----
    | > | >
    | > | > As PRINT statements are returned as warning messages, this will have
    | the
    | > | > same consequence as producing real warnings.
    | > | >
    | > | >
    | > | > Run that script on your database using classic Java code, eg:
    | > | >
    | > | > statement.execute(loadedSqlScriptContent); // Send content of
    the
    | > sql
    | > | > script to the server
    | > | > resultSet = statement.getResultSet(); // This will get a null
    | object
    | > | as
    | > | > you update nothing
    | > | > SQLWarning warning = statement.getWarnings(); // Get
    print/warning
    | > | > messages
    | > | >
    | > | > The third line should cause a java.lang.StackOverFlowError as the
    | number
    | > | of
    | > | > warning messages to construct is huge.
    | > | >
    | > | >
    | > | > So I would have 2 questions:
    | > | >
    | > | > - does anyone has any idea of how to solve this issue without simply
    | > | > increasing the JVM stack size ? (you can keep suggestions like
    "don't
    | > | > retrieve the warnings", etc. :).
    | > | >
    | > | > - does anyone who I should contact to have this issue possibly fixed
    | > into
    | > | > next JDBC driver's release ?
    | > | >
    | > | >
    | > | > Any answer to any of these 2 questions would be just great.
    | > | >
    | > | > Thanks a lot by advance.
    | > | >
    | > | >
    | > | > Alexandre Delarge.
    | > | >
    | > | >
    | > |
    | > |
    | > |
    | >
    | > Hi Alexandre,
    | >
    | > I created the stored procedure and Java code using the information you
    | > posted originally, but I am unable to reproduce the problem you
    describe.
    | > My source script contains over 250,000 PRINT statements, but it does
    | > eventually complete without any problems. I am using JDBC SP3 and the
    | > 1.4.2 IBM JDK. Can you post the actual code that reproduces the error?
    | >
    | > Carb Simien, MCSE MCDBA MCAD
    | > Microsoft Developer Support - Web Data
    | >
    | > Please reply only to the newsgroups.
    | > This posting is provided "AS IS" with no warranties, and confers no
    | rights.
    | >
    | > Are you secure? For information about the Strategic Technology
    Protection
    | > Program and to order your FREE Security Tool Kit, please visit
    | > http://www.microsoft.com/security.
    | >
    |
    |
    |

    Hi Alexandre,

    I was able to reproduce this problem using a few different JVMs. I will
    need to look into the matter further to determine if the current
    implementation of getWarnings() was designed to handle this number of
    messages.

    Carb Simien, MCSE MCDBA MCAD
    Microsoft Developer Support - Web Data

    Please reply only to the newsgroups.
    This posting is provided "AS IS" with no warranties, and confers no rights.

    Are you secure? For information about the Strategic Technology Protection
    Program and to order your FREE Security Tool Kit, please visit
    http://www.microsoft.com/security.


  • Next message: Carb Simien [MSFT]: "RE: JDBC Driver for SQLServer 7"

    Relevant Pages

    • Re: [PATCH 1/2] Synaptics rate switching
      ... warning messages, but that just corresponds to half the number of packets. ... In a really cold room I get nearly no warnings at all. ... scamming these things out, all kinds of James Bondian ideas come forth, but ... send the line "unsubscribe linux-kernel" in ...
      (Linux-Kernel)
    • Re: Problem in nested sorts
      ... I get warnings with and without the print statements. ... Perl level. ... "Reply" at the bottom of the article headers. ...
      (comp.lang.perl.misc)
    • [RFC] spinlock_t & rwlock_t break_lock member initialization (patch seeking comments included)
      ... and of course I see a lot of warning messages. ... down on the number of warnings I have to sift through. ... I've come up with a patch to that silence those warnings by making sure ...
      (Linux-Kernel)
    • Event ID 2012 from SRV - Network Error
      ... Warning messages with Event ID 2012 from SRV. ... "While transmitting or receiving data, ... a possible error in your network configuration. ... At first the warnings were rare but as load has ...
      (microsoft.public.windows.server.networking)
    • Re: Perl module Net::Oping Error
      ... use warnings; ... and get_recv_ttl is a hashref (which is consistent with what you got ... in your print statements). ...
      (perl.beginners)