Kathey Marsden wrote:
I got this analysis from a user and am not quite sure what to make of
it yet, but thought I would forward it to the
list to see if anyone has opinions or it makes more sense to them than
it does to me at this point. Here's the note.
"I've found a few app ClassLoader leaks in Derby.
...The first one looks like Derby created a long-running thread and
copying the context class loader. To fix, the context class loader
should be saved/set/restored around the creation of the new thread so
that it copies some benign class loader instead (e.g., null or
getClass().getClassLoader()):
0x42278e58 java/lang/[EMAIL PROTECTED]
[truncating at running thread LEAK]
Object: 0x42278e58 java/lang/[EMAIL PROTECTED]
Children:
0x42278ee0 java/lang/[EMAIL PROTECTED]
0x4226e558 java/lang/[EMAIL PROTECTED]
0x42278e40 org/apache/derby/impl/services/monitor/[EMAIL PROTECTED]
0x419cfac0
The second is another long running thread. The same applies:
0x426fe7a0 java/lang/[EMAIL PROTECTED]
[truncating at running thread LEAK]
Object: 0x426fe7a0 java/lang/[EMAIL PROTECTED]
Parents:
0x4226e5a8 [Ljava/lang/Thread;@6f386f38
0x426fe548 org/apache/derby/iapi/services/context/[EMAIL PROTECTED]
Children:
0x426fe838 java/lang/[EMAIL PROTECTED]
0x4226e558 java/lang/[EMAIL PROTECTED]
0x426fe4f8 org/apache/derby/impl/services/daemon/[EMAIL PROTECTED]
0x419cfac0
The third is a TimerThread owneed , which is created when a Timer is
created. The same applies:
0x425ac538 java/util/[EMAIL PROTECTED]
[truncating at running thread LEAK]
Object: 0x425ac538 java/util/[EMAIL PROTECTED]
Parents:
0x41faaf58 [Ljava/lang/Thread;@3c583c58
Object: 0x425ac510 java/util/[EMAIL PROTECTED]
Parents:
0x425ac500
org/apache/derby/impl/services/timer/[EMAIL PROTECTED]
6e2
Thanks for any input. I will follow up with the user and see if I can
get some more details and translate into something we can file in Jira.
I got some more information on this issue. The user modified a simple
derby program to "show the leak". This work's only with IBM jdk's.
Here is the comment that went with the program:
"I create a new BJKCL and set it as the context class loader. Then, we
interact with Derby and clean up the context class loader. Finally, run
a GC which should allow the temporary BJKCL to be cleaned up, and then
generate a javacore/heapdump. In an app server scenario, that would
translate as "BJKCL is the app CL", and the "interact with Derby" is an
application doing a JNDI DataSource lookup for the first time. Of
course, we never want to shut down Derby in the app server, so I had to
remove that bit to keep things alive."
Thanks again for any input. I'm still not totally clear on what is
going on here.
Kathey
import java.sql.*;
public class SimpleDerbyProgramShowLeak {
public static void main(String[] args) throws Exception{
// setup
Thread.currentThread().setContextClassLoader(new BJKCL());
// use derby
Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance();
((BJKCL)Thread.currentThread().getContextClassLoader()).defineClass().newInstance();
// cleanup
Thread.currentThread().setContextClassLoader(null);
// generate dumps
System.gc();
com.ibm.jvm.Dump.HeapDump();
com.ibm.jvm.Dump.JavaDump();
}
public SimpleDerbyProgramShowLeak() throws Exception {
Connection conn =
DriverManager.getConnection("jdbc:derby:wombat;create=true");
Statement s = conn.createStatement();
ResultSet rs = s.executeQuery("SELECT COUNT(*) from SYS.SYSTABLES");
rs.next();
System.out.println("count of systables = " + rs.getString(1));
/*
// Shutdown derby. We expect an exception on shutdown
try {
DriverManager.getConnection("jdbc:derby:;shutdown=true");
} catch (SQLException se) {
}
*/
}
}
class BJKCL extends ClassLoader {
Class defineClass() throws Exception {
byte[] b = new byte[4096];
return defineClass(b, 0, new
java.io.FileInputStream("SimpleDerbyProgramShowLeak.class").read(b));
}
}