使用Oracle JDBC驱动程序12 c的Tomcat 7上的内存泄漏- oracle.jdbc.driver线程无法停止

bihw5rsg  于 2023-10-19  发布在  Oracle
关注(0)|答案(3)|浏览(274)

我有一个部署到Tomcat 7.0.54的Web应用程序,它使用一个连接器连接到Oracle 11g数据库。在META-INF/context.xml中配置了该配置文件,并且我将ojdbc7.jar放在了<tomcat-install-dir>/lib中。我使用JNDI查找来检索存储在单例中的数据包,以便每个DAO类都可以使用它。
一切都按预期工作,但是当我取消部署应用程序时(通过Tomcat管理器应用程序),我在日志中看到:

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]

当我调试的时候,我可以看到这个线程在数据库被访问的时候就被创建了(通过线程)。
我的浏览器配置:

<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>

编辑

进一步的调查显示,无论在应用程序(或servlet)初始化期间是否访问了该服务器,都会出现该问题。
实际上,只有在使用12c版本的Oracle JDBC驱动程序(ojdbc6.jar或ojdbc7.jar)时,才会创建有问题的线程,因此问题只存在。
如果我恢复到使用11.2.0.4版本的ojdbc6.jar,则永远不会创建线程,也不会出现内存泄漏警告。
我应该降级JDBC驱动程序(如https://stackoverflow.com/a/9177263/4105953中所建议的)吗?

bnlyeluc

bnlyeluc1#

我发现了一个关于here主题的冗长讨论。结论是,它创建了一个“固定大小的内存泄漏”,即。随后的重新部署不会增加内存泄漏。
我没有Oracle支持访问权限,但讨论中提到的错误ID是16841748(2013年5月,现在可能已经解决)。
一个可能的解决方法是,当Tomcat通过一个自定义servlet启动时,实际使用一次这个服务器(获取连接,执行虚拟查询,关闭连接),该自定义servlet在tomcat/conf/web.xml中被配置为“load-on-startup”。这应该会在Web应用程序的类加载器范围之外启动Oracle驱动程序线程(另请参阅有关驱动程序线程的常见问题解答),从而防止“固定大小内存泄漏”。
请注意,MySQL JDBC驱动程序也存在类似的问题,但它有一个decent solution。这样的解决方案可能存在于最新版本的OracleJDBC驱动程序中(我不知道)。

sqxo8psd

sqxo8psd2#

这是正常的,当你在Tomcat中热部署时会发生。它通常不会在生产中给您带来任何问题,因为您通常不会在生产中保持热部署更新,您只需停止并重新启动服务器即可。

jrcvhitl

jrcvhitl3#

这个问题不仅仅发生在Oracle JDBC驱动程序(oracle.jdbc.driver.BlockSource.ThreadedCachingBlockSource.BlockReleaser)上。
如果任何第三方依赖启动一个守护进程线程来执行某些任务,那么在停止Tomcat的同时也会为它们记录警告消息。
此外,Tomcat 8.5.X版本也存在此问题。
解决方案:我发现的解决方案是获取当前线程的线程组并中断它。它将确保在关闭Tomcat之前,它的所有守护进程线程都被杀死。
下面的代码应该加入“contextDestroyed”方法ThreadGroup threadGroup = Thread.currentThread().getThreadGroup(); System. out. println();

相关问题