我将在接下来的几行中介绍有关该应用程序的一些背景信息:
XYZ 是一个数据屏蔽工作台 eclipse RCP 应用程序:您给它一个源表列和一个目标表列,它将应用转换(加密/改组/等)并复制该行从源表到目标表的数据。现在,当我一次屏蔽 n 个表时,此应用程序将启动 n 个线程。
问题是:
我在首次推出上述应用时遇到了生产问题。不幸的是,我没有任何日志可以到达根目录。但是,我尝试在测试区域运行此应用程序并进行压力测试。
当我收集 .hprof 文件并通过分析器 (yourKit) 运行它们时,我注意到 oracle.jdbc.driver.T4CPreparedStatement 的对象保留了堆。分析还告诉我,我的一个类持有对这个 preparedstatement 对象的引用,因此,n 个线程有 n 个这样的对象。 T4CPreparedStatement 似乎有字符数组:lastBoundChars 和 bindChars,每个大小都是 char[300000]。
所以,我研究了一下(谷歌!),获得了 ojdbc6.jar 并尝试反编译 T4CPreparedStatement。我看到 T4CPreparedStatement 扩展了 OraclePreparedStatement,它动态管理 lastBoundChars 和 bindChars 的数组大小。
所以,我的问题是:
- 你有没有遇到过这样的问题 这个?
- 你知道的意义吗 lastBoundChars/bindChars?
- 我是分析新手,你也是 认为我做的不正确? (我 还通过 MAT 运行了 hprofs - 这是主要确定的 问题 - 所以,我真的不认为我 可能是错的?)
我在网上找到了类似的东西: http://forums.oracle.com/forums/thread.jspa?messageID=2860681
感谢您的建议/忠告。
最佳答案
我遇到了同样的问题。尽管 Affe 的泄漏可能是问题所在,但这不是我的问题,经过一番挖掘后我找到了不同的答案:
Oracle JDBC 驱动程序维护缓冲区,将数据读入缓冲区以优化性能。缓冲区大小是根据可能的最大行大小(因此 VARCHAR(2000)
将分配类似 2000 个 char
的内容)乘以 JDBC 提取大小计算得出的。这允许驱动程序直接将数据读入缓冲区,而不是按需分配(显然)速度较慢。
每个连接中的每个准备好的语句都维护一个这种缓冲区。如果您正在使用带有语句缓存的大型连接池(或者您手动缓存 PreparedStatement
对象,或者泄漏它们...),那么您会迅速耗尽大量堆空间。我的情况是 1.6GB!
这一切都由 Oracle 自己在 PDF here 中解释。
我的体验是基于11.2.0.3驱动。
关于java - Oracle T4CPreparedStatement 内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2876895/