You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-user@db.apache.org by Jason von Nieda <ja...@vonnieda.org> on 2010/04/12 22:29:21 UTC

Derby causing a classloader leak

Hi all,

I have been tasked with finding a classloader leak in our application and I
have been slowly tracking it down to the Derby embedded driver. To test this
I wrote a small test case outside of our application that simply loads Derby
into a second classloader and causes it to create a drop a table. These
actions, even after the proper Derby shutdown procedures cause the
classloader to not be unloadable. Can someone take a look at the code below
and tell me if I am missing something, or is this perhaps a known issue?
I've done quite a bit of searching and the main thing I found was
https://issues.apache.org/jira/browse/DERBY-3745 which seems to have been
fixed.

I am using Derby 10.5.3.0.

Interestingly, I have found that loading the driver and opening a connection
doesn't cause the leak but any execution of a statement does.

The code I am using to test this is at http://pastebin.com/pJBdGBVT . Main
is the test case itself, Test is the class which is used to load Main into a
child classloader and TestClassloader is just an extension of URLClassLoader
that lets me see when it has been finalized.

Of note is that if I don't execute the two statements the case does not
leak. I have also tested this with hsqldb and after adding the Logging
shutdown at the end of stop() it also does not leak.

Thanks,
Jason

Re: Derby causing a classloader leak

Posted by Alan Burlison <Al...@oracle.com>.
On 12/04/2010 23:54, Jason von Nieda wrote:

> if I
> run this test code in a loop instead of a single run it eventually causes an
> OOM PermGen space, which is the same error our app experiences after a few
> restarts. By simply not running the two SQL statements the test can run
> indefinitely without an OOM.

Are you calling close() on all the statement and result handles?

-- 
Alan Burlison
--

Re: Derby causing a classloader leak

Posted by Jason von Nieda <ja...@vonnieda.org>.
Hi Raymond, thank you for your response.

It's a few things. First, yes, the finalizer is not called in the case of
the leak. Second, I am using YourKit profiler and in the case of the leak I
can see many Derby classes still loaded along with the classloader that
loaded them. Also, I have been using jmap and jhat to dump the heap and look
at the loaded classes and in the cases that I am calling "leak" the Derby
classes are still loaded. Finally, the reason for all my work on this, if I
run this test code in a loop instead of a single run it eventually causes an
OOM PermGen space, which is the same error our app experiences after a few
restarts. By simply not running the two SQL statements the test can run
indefinitely without an OOM.

Thanks,
Jason




On Mon, Apr 12, 2010 at 3:40 PM, Raymond Kroeker <ra...@gmail.com>wrote:

> Can you describe the symptom of a leak?  Is it that the finalizer
> isn't called or is there some other criteria by which the judgement is
> being made?
>
> Raymond
>
> On Mon, Apr 12, 2010 at 13:29, Jason von Nieda <ja...@vonnieda.org> wrote:
> > Hi all,
> > I have been tasked with finding a classloader leak in our application and
> I
> > have been slowly tracking it down to the Derby embedded driver. To test
> this
> > I wrote a small test case outside of our application that simply loads
> Derby
> > into a second classloader and causes it to create a drop a table. These
> > actions, even after the proper Derby shutdown procedures cause the
> > classloader to not be unloadable. Can someone take a look at the code
> below
> > and tell me if I am missing something, or is this perhaps a known issue?
> > I've done quite a bit of searching and the main thing I found
> > was https://issues.apache.org/jira/browse/DERBY-3745 which seems to have
> > been fixed.
> > I am using Derby 10.5.3.0.
> > Interestingly, I have found that loading the driver and opening a
> connection
> > doesn't cause the leak but any execution of a statement does.
> > The code I am using to test this is at http://pastebin.com/pJBdGBVT .
> Main
> > is the test case itself, Test is the class which is used to load Main
> into a
> > child classloader and TestClassloader is just an extension of
> URLClassLoader
> > that lets me see when it has been finalized.
> > Of note is that if I don't execute the two statements the case does not
> > leak. I have also tested this with hsqldb and after adding the Logging
> > shutdown at the end of stop() it also does not leak.
> > Thanks,
> > Jason
> >
>
>
>
> --
> ---------------------------------------------------------
> Raymond Kroeker
>

Re: Derby causing a classloader leak

Posted by Raymond Kroeker <ra...@gmail.com>.
Can you describe the symptom of a leak?  Is it that the finalizer
isn't called or is there some other criteria by which the judgement is
being made?

Raymond

On Mon, Apr 12, 2010 at 13:29, Jason von Nieda <ja...@vonnieda.org> wrote:
> Hi all,
> I have been tasked with finding a classloader leak in our application and I
> have been slowly tracking it down to the Derby embedded driver. To test this
> I wrote a small test case outside of our application that simply loads Derby
> into a second classloader and causes it to create a drop a table. These
> actions, even after the proper Derby shutdown procedures cause the
> classloader to not be unloadable. Can someone take a look at the code below
> and tell me if I am missing something, or is this perhaps a known issue?
> I've done quite a bit of searching and the main thing I found
> was https://issues.apache.org/jira/browse/DERBY-3745 which seems to have
> been fixed.
> I am using Derby 10.5.3.0.
> Interestingly, I have found that loading the driver and opening a connection
> doesn't cause the leak but any execution of a statement does.
> The code I am using to test this is at http://pastebin.com/pJBdGBVT . Main
> is the test case itself, Test is the class which is used to load Main into a
> child classloader and TestClassloader is just an extension of URLClassLoader
> that lets me see when it has been finalized.
> Of note is that if I don't execute the two statements the case does not
> leak. I have also tested this with hsqldb and after adding the Logging
> shutdown at the end of stop() it also does not leak.
> Thanks,
> Jason
>



-- 
---------------------------------------------------------
Raymond Kroeker

Re: Derby causing a classloader leak

Posted by Kathey Marsden <km...@sbcglobal.net>.
On 4/12/2010 5:02 PM, Jason von Nieda wrote:
> Hi Kathey,
>
> Thanks for the code samples. Unfortunately this didn't do the trick. I 
> am still getting the leaked classloader using the shutdown method you 
> sent over. As before, if I comment just the two stmt.execute() lines 
> the classloader unloads properly. It seems like something happens in 
> the driver once the first statement is executed that causes it to hang 
> on to the classloader.
>
> And to Alan, yes, I am closing the statement. I've also tried 
> explicitly closing the statement and creating a new one for each 
> command. That also fails.
>
Can you post your new code with the shutdown using the right class 
loader.  If the shutdown is indeed happening with the right class loader 
and possibly even if it is not, I would think there's a bug there, 
somewhere.  I will backport DERBY-4598 to 10.5 in the next few days and 
then if you can try that out and verify the shutdown is  correct, I 
think you should file a bug.

thanks

Kathey




Re: Derby causing a classloader leak

Posted by Raymond Kroeker <ra...@gmail.com>.
My concern is that there is NO guarantee as to WHEN the finalizers on
objects are called.  You can call gc until you're blue in the face and
there is no onus on the JVM to finalize your objects.

Same goes for loaded classes, they get removed when the JVM just
bloody well feels like it, so my though on these as indicators of a
leak is low.

Can you provide a sample of your test with the loop?  I would lean
towards Alan's response of a physical resource not being released by
the code-within-the-loop.  I have had good luck load testing
applications using both embedded and network drivers for version
10.2.2.0 (I know it's older) and every time it's been the app (or
connection pool) holding on to statements/results or connections.

Good luck.

Raymond

On Tue, Apr 13, 2010 at 02:08, Alan Burlison <Al...@oracle.com> wrote:
> On 13/04/2010 01:02, Jason von Nieda wrote:
>
>> And to Alan, yes, I am closing the statement. I've also tried explicitly
>> closing the statement and creating a new one for each command. That also
>> fails.
>
> OK, was just a thought - I've seen leakage in the past because of that.
>
> --
> Alan Burlison
> --
>



-- 
---------------------------------------------------------
Raymond Kroeker

Re: Derby causing a classloader leak

Posted by Alan Burlison <Al...@oracle.com>.
On 13/04/2010 01:02, Jason von Nieda wrote:

> And to Alan, yes, I am closing the statement. I've also tried explicitly
> closing the statement and creating a new one for each command. That also
> fails.

OK, was just a thought - I've seen leakage in the past because of that.

-- 
Alan Burlison
--

Re: Derby causing a classloader leak

Posted by Jason von Nieda <ja...@vonnieda.org>.
Hi Kathey,

Thanks for the code samples. Unfortunately this didn't do the trick. I am
still getting the leaked classloader using the shutdown method you sent
over. As before, if I comment just the two stmt.execute() lines the
classloader unloads properly. It seems like something happens in the driver
once the first statement is executed that causes it to hang on to the
classloader.

And to Alan, yes, I am closing the statement. I've also tried explicitly
closing the statement and creating a new one for each command. That also
fails.

Jason


On Mon, Apr 12, 2010 at 4:20 PM, Kathey Marsden <kmarsdenderby@sbcglobal.net
> wrote:

> On 4/12/2010 1:29 PM, Jason von Nieda wrote:
>
>> Hi all,
>>
>>
>>  These actions, even after the proper Derby shutdown procedures cause the
>> classloader to not be unloadable. Can someone take a look at the code below
>> and tell me if I am missing something, or is this perhaps a known issue?
>>
> The important thing I think is to shutdown using the same class loader in
> which Derby is booted.   Below are some code snippets to do this.   I
> recently checked in a change to 10.6 that shows the class loader for boot
> and shutdown.  I'll be backporting that soon to 10.5.  The problem I have
> mostly seen with using the wrong class loader to shutdown is that a
> subsequent boot attempt fails.
>
>
>
>
>
> If you don't have direct access to the class loader, you can get it from
> the connection with getClassLoader()
>
> e.g.
>
>    shutdownWithLoader(conn.getClass().getClassLoader());
>
>
>
>  private static void shutdownWithLoader(ClassLoader loader) throws
> Exception {
>    DataSource ds = newDataSource(loader,"");
>    Class[] argType = {String.class};
>    String[] args = new String[] {"shutdown"};
>    Method sh = ds.getClass().getMethod("setShutdownDatabase", argType);
>    sh.invoke(ds, (Object[]) args);
>
>    try {
>        ds.getConnection();
>    }catch (SQLException se ) {
>        if (se.getSQLState().equals("XJ015")) {
>        System.out.println("Normal Shutdown");
>        }
>        else
>        throw se;
>    }
>
>    }
>
>
>
>    private static DataSource newDataSource(ClassLoader loader, String
> databaseName) throws Exception
>    {
>        DataSource ds = (DataSource)
> loader.loadClass("org.apache.derby.jdbc.EmbeddedDataSource").newInstance();
>        // setDatabaseName with reflection
>        Class[] argType = {String.class};
>        String[] args = new String[] {databaseName};
>        Method sh = ds.getClass().getMethod("setDatabaseName", argType);
>        sh.invoke(ds, (Object[]) args);
>        return ds;
>
>    }
>
>
>

Re: Derby causing a classloader leak

Posted by Kathey Marsden <km...@sbcglobal.net>.
On 4/12/2010 1:29 PM, Jason von Nieda wrote:
> Hi all,
>
>  These actions, even after the proper Derby shutdown procedures cause 
> the classloader to not be unloadable. Can someone take a look at the 
> code below and tell me if I am missing something, or is this perhaps a 
> known issue?
The important thing I think is to shutdown using the same class loader 
in which Derby is booted.   Below are some code snippets to do this.   I 
recently checked in a change to 10.6 that shows the class loader for 
boot and shutdown.  I'll be backporting that soon to 10.5.  The problem 
I have mostly seen with using the wrong class loader to shutdown is that 
a subsequent boot attempt fails.





If you don't have direct access to the class loader, you can get it from 
the connection with getClassLoader()

e.g.

     shutdownWithLoader(conn.getClass().getClassLoader());



   private static void shutdownWithLoader(ClassLoader loader) throws 
Exception {
     DataSource ds = newDataSource(loader,"");
     Class[] argType = {String.class};
     String[] args = new String[] {"shutdown"};
     Method sh = ds.getClass().getMethod("setShutdownDatabase", argType);
     sh.invoke(ds, (Object[]) args);

     try {
         ds.getConnection();
     }catch (SQLException se ) {
         if (se.getSQLState().equals("XJ015")) {
         System.out.println("Normal Shutdown");
         }
         else
         throw se;
     }

     }



     private static DataSource newDataSource(ClassLoader loader, String 
databaseName) throws Exception
     {
         DataSource ds = (DataSource) 
loader.loadClass("org.apache.derby.jdbc.EmbeddedDataSource").newInstance();
         // setDatabaseName with reflection
         Class[] argType = {String.class};
         String[] args = new String[] {databaseName};
         Method sh = ds.getClass().getMethod("setDatabaseName", argType);
         sh.invoke(ds, (Object[]) args);
         return ds;

     }