Memory leak on Tomcat 7 with Oracle JDBC 12c drivers - oracle.jdbc.driver thread failed to stop

I have a web application deployed in Tomcat 7.0.54 that uses a data source to connect to an Oracle 11g database. The data source is configured in META-INF/context.xml and I placed ojdbc7.jar in <tomcat-install-dir>/lib . I use JNDI lookup to retrieve a data source that I store in singleton mode so that every DAO class can use it.

Everything works as expected, however, when I postpone the application (through the Tomcat manager application), I see in the logs:

 Oct 03, 2014 3:06:55 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads SEVERE: The web application [/myapp] appears to have started a thread named [oracle.jdbc.driver.BlockSource.ThreadedCachingBlockSource.BlockReleaser] but has failed to stop it. This is very likely to create a memory leak. Oct 03, 2014 3:06:57 PM org.apache.catalina.startup.HostConfig undeploy INFO: Undeploying context [/myapp] 

When I debug, I see that this thread is created as soon as the database is accessed (via the data source).

My data source configuration:

 <Context antiResourceLocking="false"> <Resource name="jdbc/myapp" auth="Container" type="javax.sql.DataSource" driverClassName="oracle.jdbc.OracleDriver" maxActive="20" maxIdle="10" maxWait="-1" username="myuser" password="mypass" url="jdbc:oracle:thin:@myserver:1521:mysid" removeAbandoned="true" removeAbandonedTimeout="10" logAbandoned="true" validationQuery="SELECT 1 FROM DUAL" testOnBorrow="true" testOnReturn="true" testWhileIdle="true" timeBetweenEvictionRunsMillis="1800000" numTestsPerEvictionRun="3" minEvictableIdleTimeMillis="1800000" /> </Context> 

EDIT

Further research showed that the problem arises regardless of whether the data source is accessed during application (or servlet) initialization.

In fact, only the problematic thread is created, and therefore, the problem exists only when using the 12c versions of Oracle JDBC drivers (either ojdbc6.jar or ojdbc7.jar).

If I return to using version ojdbc6.jar version 11.2.0.4, the thread is never created, and a memory leak warning never appears.

Should I reduce the JDBC driver (as proposed in qaru.site/questions/81554 / ... )?

+5
source share
3 answers

I found a long discussion about the topic here . The conclusion is that it creates a β€œfixed size memory leak”, that is, subsequent redeployments will not increase memory leak.
I do not have access to Oracle Support, but the error identifier mentioned in the discussion is 16841748 (May 2013, can be resolved now).

A possible workaround is to actually use the data source once (get a connection, make a dummy request, close the connection) when Tomcat is launched through a custom servlet that is configured to "load at startup" in tomcat/conf/web.xml . This should start the Oracle driver thread (see also the driver thread FAQ ) outside the scope of the loader class of your web application, thereby preventing a fixed size memory leak.

Please note that a similar problem exists for the MySQL JDBC driver, but has a decent solution . Such a solution may exist for the latest version of the Oracle JDBC driver (I don't know).

+1
source

This is normal, this happens when you deploy to Tomcat hotly. This will not cause you any problems that usually occur during production, because you usually do not keep the hot installation of updates in production, instead you just stop and restart the server.

0
source

This problem occurs not only with the Oracle JDBC driver (oracle.jdbc.driver.BlockSource.ThreadedCachingBlockSource.BlockReleaser).

If any of the third-party dependencies starts the daemon thread to perform any task, it also stops the Tomcat log warning message for the log.

In addition, this problem exists with versions of Tomcat 8.5.X.

Solution: What I found as a solution is to get the thread group for the current thread and abort it. He will ensure that all demon streams are destroyed before Tomcat closes.

the code below should be added to the "contextDestroyed" ThreadGroup threadGroup = Thread.currentThread () method. GetThreadGroup (); threadGroup.interrupt ();

-1
source

Source: https://habr.com/ru/post/1203941/


All Articles