> > -----Original Message----- > > From: Mark Thomas [mailto:[email protected]] > > Sent: Friday, May 17, 2013 7:26 AM > > To: Tomcat Users List > > Subject: Re: Follow-up: Possible false-postive with > > JreMemoryLeakPreventionListener and Tomcat's JDBC Pool and > > OracleTimeoutPollingThread > > > > On 17/05/2013 12:31, Michael-O wrote: > > > Hi Mark, > > > > > > thanks again for the detailed answer, details inline. > > > > > >> Gesendet: Freitag, 17. Mai 2013 um 11:36 Uhr > > >> Von: "Mark Thomas" <[email protected]> > > >> An: "Tomcat Users List" <[email protected]> > > >> Betreff: Re: Follow-up: Possible false-postive with > > >> JreMemoryLeakPreventionListener and Tomcat's JDBC Pool and > > >> OracleTimeoutPollingThread > > >> > > >> On 17/05/2013 09:28, Michael-O wrote: > > >>> Hi folks, > > >>> > > >>> there's now a follow-up on the issue [1]. > > >>> Recap: JreMemoryLeakPreventionListener reported that my webapp has > > spawned OracleTimeoutPollingThread because I have set a QueryTimeout in > > the JDBC Pool. > > >>> Mark Thomas noted that this is likely a bug in the driver. I have > > taken action and created a service request with Oracle. > > >>> > > >>> My personal analysis with VisualVM: > > >>> The thread is spawned when the first query is run. The thread keeps > > running when the webapp is shut down or undeployed. Classes remain in > > memory. > > >>> The JDBC Pool does a simple Class.forName to load the driver, it > > neither uses the DriverManager loading nor does it actively unload the > > driver. > > >>> > > >>> Oracle answer: > > >>> They were able to reproduce the issue. The technical analysis says: > > >>> > > >>>> Hi Michael, > > >>>> > > >>>> I confirmned internally that this message from Tomcat can be > > ignored as there is no risk of any real leak from" > > OracleTimeoutPollingThread" thread. > > >>>> This thread is related to the JDBC driver which may be used by > > many apps simultaneously. Unloading the app does not unload the driver > > and should not and does not stop the thread. > > >>>> > > >>>> It seems to be the design behaviour. > > >>> > > >>> So my questions would be: > > >>> 1. Is that still not a false positive? > > >> > > >> No, that is not a false positive. The response from Oracle is wrong. > > >> > > >> There is nothing wrong with the driver creating the thread or the > > >> thread continuing after the web application has stopped. The problem > > is as follows: > > >> > > >> 1. When the JDBC driver creates the Thread, the Thread's context > > >> class loader (as returned by Thread.getContextClassLoader()) is set > > >> to the web application's class loader. > > >> > > >> 2. The correct behaviour at this point would be for the Driver to > > set > > >> the Thread's context class loader to the class loader that loaded > > the > > >> Driver class when the Thread is created. > > >> > > >> 3. The memory leak occurs as follows: > > >> - the web application is stopped > > >> - Tomcat clears all references to the web application and its > > classes > > >> - The web application should be eligible for garbage collection > > >> - The JDBC driver is still loaded (as it should be) > > >> - The JDBC driver retains a reference to the Thread (as it should) > > >> - The thread retains a reference to the web application class loader > > >> (this is the memory leak). > > >> > > >> The reference chain is: > > >> a) JDBC driver > > >> b) Thread > > >> c) Web application class loader > > >> d) Every class loaded by the web app > > >> > > >> Everything from c) onwards should be eligible for garbage collection > > >> but isn't because of the leak in the Thread that is retaining a > > >> reference to the web application class loader. > > > > > > This is what I would assume as correct behavior. If the thread is > > still attached ot the WebAppClassLoader, does that mean that the > > WebAppClassLoader cannot be garbage collected? > > > > The correct behaviour is that there is no reference to c) held by b) > > and therefore c) onwards would be eligible for GC (assuming the web app > > has been stopped). The problem here is that because b) has a reference > > to c), c) can't be GC'd and that is a memory leak. > > > > > > >>> 2. Why does the JDBC Pool not unload the driver? That my cause the > > thread to stop after the last app has been stopped/undeployed. > > >> > > >> 1. Because the driver is in CATALINA_HOME/lib it is available to > > >> other applications. > > > > > > So first app, loads driver and keeps it in memory. Even if all apps > > are undeployed, driver remains cached and GCed when Tomcat is shut > > down? > > > > The JDBC driver will be loaded though the services API as soon as any > > code references the DriverManager. > > > > >> 2. JDBC drivers are never automatically unloaded. You have to do so > > >> explicitly (not doing so is an other source of memory leaks when the > > >> driver is packaged in WEB-INF/lib). > > > > > > OK, this won't be the case. Driver is always shared here. > > > > > >> You need to go back to Oracle. > > > > > > Yes, I will. We're paying probably a lot of money for he company-wide > > license. > > > > I'd expect so. > > > > From my own experience with Oracle commercial support for things Java > > related, you'll have to go through the "This is a bug. No it isn't. Yes > > it is..." cycle several times before you manage to get the issue in > > front of someone with the necessary knowledge and skills to correctly > > identify this is a bug in Oracle's JDBC driver. I'd recommend > > escalating it through your account manager sooner rather than later. > > > > Feel free to point Oracle support to this thread and/or my presentation > > on memory leaks. If Oracle support require further help understanding > > this issue they are, of course, free to join this mailing list. > > > > Mark > > > > Michael and Mark - > I happened to be reviewing how Oracle handles QueryTimeout yesterday on an > unrelated issue and came across a passage in the JDBC Developers Guide (11g) > that covered this Monitoring Thread (page E-3). My reading of it was that > Oracle creates a single monitoring thread per JVM, so if there are multiple > apps utilizing the Oracle driver, you certainly don't want one app shutting > down and taking the monitor thread with it. I'm sure this one of the reasons > that Mark says that the monitor thread should use the parent class loader. > Oracle should probably consider this.
Hi Jeff, yes, your understanding correct. This Thread must be mounted one level up. The JBDC Pool suffered from a similar issue which I have discovered a few months ago. The PoolCleaner thread was one-per-JVM and did had the wrong class loader. Same applies to the Oracle driver. > My question though is how is all this affected when the jdbc library is > loaded on a per-app basis, i.e., it's not shared but loaded from each app's > WEB-INF/lib folder? Should the app then unload the driver when it shuts down > to avoid memory leaks? Or is there a special process that needs to be > followed? First of all, Mark already addressed this. When the driver is used from WEB-INF/lib, the app MUST unload the driver otherwise the webapp classloader would not be GCed. More over, the thread would still continue to run, as fasr as I understood this technique. Oracle support told me that I need to make sure that the driver is NOT in the WEB-INF/lib directory. This means to me if you go this way you are on your own and the behavior is undefined. Michael --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
