atom feed5 messages in org.apache.tomcat.usersRe: WebappClassLoaders pinned in memo...
FromSent OnAttachments
Christopher SchultzMay 31, 2013 8:39 am 
Caldarale, Charles RMay 31, 2013 9:02 am 
Christopher SchultzMay 31, 2013 11:10 am 
Christopher SchultzMay 31, 2013 12:30 pm 
Christopher SchultzMay 31, 2013 1:20 pm 
Subject:Re: WebappClassLoaders pinned in memory by java.security.ProtectionDomain objects
From:Christopher Schultz (chr@christopherschultz.net)
Date:May 31, 2013 1:20:57 pm
List:org.apache.tomcat.users

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256

All,

On 5/31/13 11:39 AM, Christopher Schultz wrote:

- Using MySQL Connector/J 5.1.24 (important later) - Not running under a SecurityManager - <Context> has no "clearReferences...*" attributes set (all default to "false" save for HttpClientKeepAlive)

WebappClassLoader ^- classloader of java.security.ProtectionDomain ^- [7] of java.security.ProtectionDomain[8] ^- context of java.security.AccessControlContext ^- inheritedAccessControlContext of com.mysql.jdbc.AbandonedConnectionCleanupThread

It seems that the AbandonedConnectionCleanupThread itself is not to blame: it hardly has any code in it at all, other than this astoundingly ineffective attempt to avoid ClassLoader leakage in the run() method:

threadRef.setContextClassLoader(null);

Connector/J 5.1.25 (one patch-version after the one I'm currently running has removed that line, so there's now a direct link from the thread to the WebappClassLoader. Brilliant.)

Anyhow, everything crystallized in Thread.init(), called from Thread.<init>, so is happens even before MySQL's thread had a chance to do anything (such as change the context ClassLoader).

The context class loader needs to be set /before/ the Thread is created, and that happens in MySQL's JDBC driver's static initializer, like this:

static { AbandonedConnectionCleanupThread referenceThread = new AbandonedConnectionCleanupThread(); referenceThread.setDaemon(true); referenceThread.start(); }

*sigh*

I've commented on the bug... we'll see if anything else happens.

It appears that using the JreMemoryLeakPreventionListener's classesToInitialize set to "com.mysql.jdbc.NonRegisteringDriver" seems to do the trick: clean reloads again.

/me sighs satisfactorily

Then again, using classesToInitialize is a total hack.

Would it be reasonable to have the context ClassLoader of the thread Tomcat is using to create the JNDI DataSource be temporarily set (if necessary) to the ClassLoader that actually loaded the Driver itself?

That way, if the driver is loaded from WEB-INF/lib, then these kinds of threads will get the WebappClassLoader as their context ClassLoader (which I believe is appropriate), and those loaded from CATALINA_BASE/lib will get the container's ClassLoader (which I believe if appropriate, since the driver shouldn't be loading webapp-specific classes).

- -chris -----BEGIN PGP SIGNATURE----- Version: GnuPG/MacGPG2 v2.0.17 (Darwin) Comment: GPGTools - http://gpgtools.org Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQIcBAEBCAAGBQJRqQZAAAoJEBzwKT+lPKRYhIAP/1fAwuGhQoeepqkbw8ed4XvL G4m80P6XC81er9KFZ0A8FImQ/Ua6w0t168TV7d6roqWl3voNC/Zvi+s1BIzmLmtX Fvs66j6sGzUdYuE6Hu8B4joyG1o4e/fJRb5IA9zdLI/cbna8n5+tFhDPtly3vnuN iJQgyVEYfdhej62lwLG/gGwIC+qUHxVgt0Z0MbRVEyKYvWX7RUWonYTrVHoH9+hG ycf6yjUQXT3DFKno9FA8cUbDZwwpMeKXz7bK2oEdfFiAVWSFp63Y5KR6RSYYNwCG DPY8POuwBGufzvQH6xRBb4TtRyZ1gt35bR4raOxK0Ls0YnnJYZHlzb41HxrQXMSP lBQpnsneQhvNURGZUKw6VU2aCdg5l+OQbWhXJF/wzFz6B2M3u9ARwvY7h/iCJx0V KECmprP3dZ717FtvVNNAs19ncr7fOVRhJqv2fRmDU+t5iklD0HROmCk00FcRUuub kJVqvOeNjE8Tjy9lZ3MviLD/Xq7CIdKfIKghHwwdB/+Mm5kXOP2DodORBScZK1ad s9X92mtbrNF5pMwL9eZJycjSZYxVoDTXqISNOjUWIIWpbz0piv4JReZrTHx2EFxw bOjEKW8K5NGrIy2xRLUjmgCl70smUqmUvPrjbIbT+EjwOe1nphi68as2aj4i9hU2 S3kJo2iGjjEbkVwLjHoy =9YG6 -----END PGP SIGNATURE-----