You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-dev@db.apache.org by Daniel John Debrunner <dj...@debrunners.com> on 2005/11/22 19:28:46 UTC

SQLExceptions and OutOfMemoryExceptions

Somewhere in the JDBC specs/api/tutorial it says that JDBC drivers
should throw SQLExceptions rather than generic exceptions. Thus a
SQLException is preferred to a NullPointerException.
[I can't find that text now, though :-(]

For out of memory exceptions, this causes somewhat of a problem. I have
code that fails gracefully if an OutOfMemoryException is thrown during
establishment of a connection. The issue is that trying to create the
new SQLException will fail due to an OutOfMemoryException. :-(

One work-around is to pre-allocate a static singleton SQLException for
this out of memory case, there are two problems with this:

- The original OutOfMemoryException cannot be chained to the singleton,
thus some useful information is lost (the original stack trace).

- Looking forward, there would need to be several (many?) singleton
SQLExceptions, for example the one I'm experimenting with has a SQLState
starting with 08 indicating a connection failure. E.g. an
OutOfMemoryException during an executeQuery would need a SQLException
with a different SQLState.

The other alternative is to directly throw the OutOfMemoryException as
this requires no new object allocation. The problem with this is that it
is less natural for applications, which will be catching SQLException
but most likely not OutOfMemoryExceptions. And it removes the
possibility of using the JDBC SQLException sub-classing to indicate that
the operation is re-tryable.

Maybe there's also the option of trying to allocate a new SQLException
and if that fails revert to using the singleton, or throwing the
original OutOfMemoryException.

Any thoughts, opinions on the best approach?

Dan.


Re: SQLExceptions and OutOfMemoryExceptions

Posted by Oy...@Sun.COM.
Daniel John Debrunner wrote:
> Oyvind.Bakksjo@Sun.COM wrote:
>>The stack trace isn't created when the Exception object is constructed,
>>it's created when it's thrown. If you throw the same exception object
>>from multiple threads, they will interfer with each other in
>>unpredictable ways.
> 
> 
> 
> That's not what I see in jdk 1.4.2, from IBM & Sun and jdk 1.5. Here's a
> simple program that creates an exception in the method b() but throws it
> in a(). I always see b() in the stack trace.
> 
> java.lang.Exception: from b
>         at te.b(te.java:20)
>         at te.a(te.java:15)
>         at te.main(te.java:6)
> 
> I've always seen exceptions have the stack trace of where they were
> created. That's also what the jdk 142 javadocs say for Throwable:
> 
> 'A throwable contains a snapshot of the execution stack of its thread at
> the time it was created'

OK, red herring from me. :-/ My memory must be playing games with me - I 
have used the "create exception" trick earlier to get the current stack 
trace, and seemed to recall that I had to actually throw-catch it to get 
the stack trace. But that can't be the case then.

-- 
Oyvind Bakksjo
Sun Microsystems, Database Technology Group
Trondheim, Norway
http://weblogs.java.net/blog/bakksjo/

Re: SQLExceptions and OutOfMemoryExceptions

Posted by Daniel John Debrunner <dj...@debrunners.com>.
Oyvind.Bakksjo@Sun.COM wrote:

> Daniel John Debrunner wrote:
> 
>> Oyvind.Bakksjo@Sun.COM wrote:

>>> You would at least need to have one per thread.

>> Why? If I have a singleton as a static and never modify it, I can safely
>> throw it in multiple threads. It will have the fixed meangingless stack
>> trace, but this to handle a special case.
> 
> 
> The stack trace isn't created when the Exception object is constructed,
> it's created when it's thrown. If you throw the same exception object
> from multiple threads, they will interfer with each other in
> unpredictable ways.


That's not what I see in jdk 1.4.2, from IBM & Sun and jdk 1.5. Here's a
simple program that creates an exception in the method b() but throws it
in a(). I always see b() in the stack trace.

java.lang.Exception: from b
        at te.b(te.java:20)
        at te.a(te.java:15)
        at te.main(te.java:6)

I've always seen exceptions have the stack trace of where they were
created. That's also what the jdk 142 javadocs say for Throwable:

'A throwable contains a snapshot of the execution stack of its thread at
the time it was created'

public class te
{
  public static void main(String[] args)
  {
      try {
        a();
      } catch (Exception e)
      {
        e.printStackTrace(System.out);
      }
  }

  public static void a() throws Exception
  {
      throw b();
  }

  public static Exception b()
  {
      return new Exception("from b");
  }
}

Dan.





Re: SQLExceptions and OutOfMemoryExceptions

Posted by Oy...@Sun.COM.
Daniel John Debrunner wrote:
> Oyvind.Bakksjo@Sun.COM wrote:
> 
> 
>>Lance J. Andersen wrote:
>>
>>
>>>I am not fond of a Singleton of a SQLException but that is just me.
>>
>>
>>You would at least need to have one per thread.
> 
> 
> 
> Why? If I have a singleton as a static and never modify it, I can safely
> throw it in multiple threads. It will have the fixed meangingless stack
> trace, but this to handle a special case.

The stack trace isn't created when the Exception object is constructed, 
it's created when it's thrown. If you throw the same exception object 
from multiple threads, they will interfer with each other in 
unpredictable ways.

-- 
Oyvind Bakksjo
Sun Microsystems, Database Technology Group
Trondheim, Norway
http://weblogs.java.net/blog/bakksjo/

Re: SQLExceptions and OutOfMemoryExceptions

Posted by Daniel John Debrunner <dj...@debrunners.com>.
Oyvind.Bakksjo@Sun.COM wrote:

> Lance J. Andersen wrote:
> 
>>
>> I am not fond of a Singleton of a SQLException but that is just me.
> 
> 
> You would at least need to have one per thread.


Why? If I have a singleton as a static and never modify it, I can safely
throw it in multiple threads. It will have the fixed meangingless stack
trace, but this to handle a special case.

Dan.


Re: SQLExceptions and OutOfMemoryExceptions

Posted by Oy...@Sun.COM.
Lance J. Andersen wrote:
> 
> I am not fond of a Singleton of a SQLException but that is just me.

You would at least need to have one per thread.

-- 
Oyvind Bakksjo
Sun Microsystems, Database Technology Group
Trondheim, Norway
http://weblogs.java.net/blog/bakksjo/

Re: SQLExceptions and OutOfMemoryExceptions

Posted by "Lance J. Andersen" <La...@Sun.COM>.

Daniel John Debrunner wrote:

>Lance J. Andersen wrote:
>
>  
>
>>Daniel John Debrunner wrote:
>>
>>    
>>
>>>Somewhere in the JDBC specs/api/tutorial it says that JDBC drivers
>>>should throw SQLExceptions rather than generic exceptions. Thus a
>>>SQLException is preferred to a NullPointerException.
>>>[I can't find that text now, though :-(]
>>> 
>>>
>>>      
>>>
>>That is correct where possible a SQLException is the correct error.  You
>>can set it cause, starting in JDBC 4 to the real culprit.
>>
>>    
>>
>>>For out of memory exceptions, this causes somewhat of a problem. I have
>>>code that fails gracefully if an OutOfMemoryException is thrown during
>>>establishment of a connection. The issue is that trying to create the
>>>new SQLException will fail due to an OutOfMemoryException. :-(
>>> 
>>>
>>>      
>>>
>>Not sure you want to jump through hoops for an OutOfMemoryException, i
>>do not think it is worth it.
>>    
>>
>
>But I do :-). We are seeing several cases where users of Derby are
>seeing OutOfMemoryExceptions, not because of memory leaks, just because
>Derby is allocating too much memory. An easy to use database would
>recover gracefully from this, and allow continued operation as best as
>possible.
>
>http://issues.apache.org/jira/browse/DERBY-443
>
>  
>
>>>One work-around is to pre-allocate a static singleton SQLException for
>>>this out of memory case, there are two problems with this:
>>>
>>>- The original OutOfMemoryException cannot be chained to the singleton,
>>>thus some useful information is lost (the original stack trace).
>>>
>>>- Looking forward, there would need to be several (many?) singleton
>>>SQLExceptions, for example the one I'm experimenting with has a SQLState
>>>starting with 08 indicating a connection failure. E.g. an
>>>OutOfMemoryException during an executeQuery would need a SQLException
>>>with a different SQLState.
>>>
>>>The other alternative is to directly throw the OutOfMemoryException as
>>>this requires no new object allocation. The problem with this is that it
>>>is less natural for applications, which will be catching SQLException
>>>but most likely not OutOfMemoryExceptions. And it removes the
>>>possibility of using the JDBC SQLException sub-classing to indicate that
>>>the operation is re-tryable.
>>>
>>>Maybe there's also the option of trying to allocate a new SQLException
>>>and if that fails revert to using the singleton, or throwing the
>>>original OutOfMemoryException.
>>> 
>>>
>>>      
>>>
>>If you are out of memory, will there ever be a chance to create a new
>>SQLException object?
>>    
>>
>
>Yes, the process of throwing an exception can catching it further up the
>stack will allow objects to be garbage collected that were only
>referened from local variables. A simple example,
>
>    byte[] A1= new byte[10000];
>
>    byte[] A2= new byte[30000];
>
>If the OutOfMemoryException is thrown allocating A2, and caught further
>up the stack (as happens with the JDBC driver], then the memory for A1
>can be collected.
>  
>
Assuming the GC has had time to run.  So I guess you can do what you 
suggest, try and  create a new SQLException and if not punt and throw 
the OutOfMemoryException.

I am not fond of a Singleton of a SQLException but that is just me.

>Or even simpler, if I try to allocate 1Mb and fail, there is probably
>still enough memory to allocate a SQLException.
>
>Thanks,
>Dan.
>
>  
>

Re: SQLExceptions and OutOfMemoryExceptions

Posted by Daniel John Debrunner <dj...@debrunners.com>.
Lance J. Andersen wrote:

> Daniel John Debrunner wrote:
> 
>> Somewhere in the JDBC specs/api/tutorial it says that JDBC drivers
>> should throw SQLExceptions rather than generic exceptions. Thus a
>> SQLException is preferred to a NullPointerException.
>> [I can't find that text now, though :-(]
>>  
>>
> That is correct where possible a SQLException is the correct error.  You
> can set it cause, starting in JDBC 4 to the real culprit.
> 
>> For out of memory exceptions, this causes somewhat of a problem. I have
>> code that fails gracefully if an OutOfMemoryException is thrown during
>> establishment of a connection. The issue is that trying to create the
>> new SQLException will fail due to an OutOfMemoryException. :-(
>>  
>>
> Not sure you want to jump through hoops for an OutOfMemoryException, i
> do not think it is worth it.

But I do :-). We are seeing several cases where users of Derby are
seeing OutOfMemoryExceptions, not because of memory leaks, just because
Derby is allocating too much memory. An easy to use database would
recover gracefully from this, and allow continued operation as best as
possible.

http://issues.apache.org/jira/browse/DERBY-443

>> One work-around is to pre-allocate a static singleton SQLException for
>> this out of memory case, there are two problems with this:
>>
>> - The original OutOfMemoryException cannot be chained to the singleton,
>> thus some useful information is lost (the original stack trace).
>>
>> - Looking forward, there would need to be several (many?) singleton
>> SQLExceptions, for example the one I'm experimenting with has a SQLState
>> starting with 08 indicating a connection failure. E.g. an
>> OutOfMemoryException during an executeQuery would need a SQLException
>> with a different SQLState.
>>
>> The other alternative is to directly throw the OutOfMemoryException as
>> this requires no new object allocation. The problem with this is that it
>> is less natural for applications, which will be catching SQLException
>> but most likely not OutOfMemoryExceptions. And it removes the
>> possibility of using the JDBC SQLException sub-classing to indicate that
>> the operation is re-tryable.
>>
>> Maybe there's also the option of trying to allocate a new SQLException
>> and if that fails revert to using the singleton, or throwing the
>> original OutOfMemoryException.
>>  
>>
> If you are out of memory, will there ever be a chance to create a new
> SQLException object?

Yes, the process of throwing an exception can catching it further up the
stack will allow objects to be garbage collected that were only
referened from local variables. A simple example,

    byte[] A1= new byte[10000];

    byte[] A2= new byte[30000];

If the OutOfMemoryException is thrown allocating A2, and caught further
up the stack (as happens with the JDBC driver], then the memory for A1
can be collected.

Or even simpler, if I try to allocate 1Mb and fail, there is probably
still enough memory to allocate a SQLException.

Thanks,
Dan.


Re: SQLExceptions and OutOfMemoryExceptions

Posted by "Lance J. Andersen" <La...@Sun.COM>.

Daniel John Debrunner wrote:

>Somewhere in the JDBC specs/api/tutorial it says that JDBC drivers
>should throw SQLExceptions rather than generic exceptions. Thus a
>SQLException is preferred to a NullPointerException.
>[I can't find that text now, though :-(]
>  
>
That is correct where possible a SQLException is the correct error.  You 
can set it cause, starting in JDBC 4 to the real culprit.

>For out of memory exceptions, this causes somewhat of a problem. I have
>code that fails gracefully if an OutOfMemoryException is thrown during
>establishment of a connection. The issue is that trying to create the
>new SQLException will fail due to an OutOfMemoryException. :-(
>  
>
Not sure you want to jump through hoops for an OutOfMemoryException, i 
do not think it is worth it.

>One work-around is to pre-allocate a static singleton SQLException for
>this out of memory case, there are two problems with this:
>
>- The original OutOfMemoryException cannot be chained to the singleton,
>thus some useful information is lost (the original stack trace).
>
>- Looking forward, there would need to be several (many?) singleton
>SQLExceptions, for example the one I'm experimenting with has a SQLState
>starting with 08 indicating a connection failure. E.g. an
>OutOfMemoryException during an executeQuery would need a SQLException
>with a different SQLState.
>
>The other alternative is to directly throw the OutOfMemoryException as
>this requires no new object allocation. The problem with this is that it
>is less natural for applications, which will be catching SQLException
>but most likely not OutOfMemoryExceptions. And it removes the
>possibility of using the JDBC SQLException sub-classing to indicate that
>the operation is re-tryable.
>
>Maybe there's also the option of trying to allocate a new SQLException
>and if that fails revert to using the singleton, or throwing the
>original OutOfMemoryException.
>  
>
If you are out of memory, will there ever be a chance to create a new 
SQLException object?

>Any thoughts, opinions on the best approach?
>
>Dan.
>
>  
>