如何阻止或停止Oracle 23 JDBC Driver的Diagnostic.CLOCK线程?
解决Oracle 23 JDBC驱动导致Tomcat关闭时的Diagnostic.CLOCK线程内存泄漏警告
针对Tomcat关闭时出现的oracle.jdbc.diagnostics.Diagnostic.CLOCK线程未停止的内存泄漏警告,提供以下几种可行的解决方法:
禁用JDBC诊断功能
该线程属于Oracle JDBC诊断模块的定时器线程,直接关闭诊断功能即可避免它被创建。可以通过两种方式设置:- 在Tomcat启动参数中添加:
-Doracle.jdbc.diagnostics.enabled=false - 在应用初始化代码中提前设置系统属性:
System.setProperty("oracle.jdbc.diagnostics.enabled", "false");
- 在Tomcat启动参数中添加:
Web应用销毁时手动清理线程
编写一个Servlet上下文监听器,在应用销毁时定位该线程并强制停止:import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import java.lang.reflect.Field; import java.util.Timer; public class OracleJdbcThreadCleanupListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) {} @Override public void contextDestroyed(ServletContextEvent sce) { ThreadGroup rootGroup = Thread.currentThread().getThreadGroup(); while (rootGroup.getParent() != null) { rootGroup = rootGroup.getParent(); } Thread[] threads = new Thread[rootGroup.activeCount()]; rootGroup.enumerate(threads, true); for (Thread thread : threads) { if (thread != null && "oracle.jdbc.diagnostics.Diagnostic.CLOCK".equals(thread.getName())) { try { // 通过反射获取关联的Timer实例并取消 Field timerField = thread.getClass().getDeclaredField("this$0"); timerField.setAccessible(true); Timer diagnosticTimer = (Timer) timerField.get(thread); diagnosticTimer.cancel(); thread.interrupt(); } catch (Exception e) { e.printStackTrace(); } } } } }随后在
web.xml中注册该监听器:<listener> <listener-class>com.your.package.OracleJdbcThreadCleanupListener</listener-class> </listener>升级到最新的Oracle 23c JDBC驱动
这个问题大概率是Oracle 23c JDBC驱动的已知bug,后续官方发布的补丁版本可能已经修复了线程未正确销毁的问题,建议尝试升级到最新的官方驱动版本。
内容的提问来源于stack exchange,提问作者Awk Omo
相关产品推荐
相关产品推荐

