--下面几行我将要讨论的应用程序的一些背景知识:
XYZ是一个数据掩蔽工作台eclipse应用程序:给它一个源表列和一个目标表列,它将应用一个转换(加密/洗牌/等),并将行数据从源表复制到目标表。现在,当我一次屏蔽n个表时,这个应用程序会启动n个线程。
这里有个问题:
我遇到了一个生产问题,在第一次推出上述应用程序。不幸的是,我没有任何日志可以找到根目录。然而,我试着在测试区域运行这个应用程序并做一个压力测试。
当我收集.hprof文件并通过分析器(yourKit)运行它们时,我注意到oracle.jdbc.driver.T4CPreparedStatement的对象保留着堆。分析还告诉我,我的一个类保存了对这个前置语句对象的引用,因此,n个线程有n个这样的对象。T4CPreparedStatement似乎有字符数组: lastBoundChars和bindChars,每个bindChars的大小都是char300000。
因此,我研究了bit (google!),获得了ojdbc6.jar,并尝试了反编译T4CPreparedStatement。我看到T4CPreparedStatement扩展了OraclePreparedStatement,它动态地管理lastBoundChars和bindChars的数组大小。
所以,我在这里的问题是:
我在网上发现了类似的东西:http://forums.oracle.com/forums/thread.jspa?messageID=2860681
感谢你的建议/建议。
发布于 2010-05-20 19:27:23
虽然有可能,但你似乎不太可能在11g中发现一个巨大的内存泄漏。首先,我将从泄漏的游标中获取实际的SQL,并查找创建该SQL的代码。我在过去发现的泄漏游标的一个非常常见的原因是这样的代码:
try {
PreparedStatment stmt = null;
stmt = con.prepareStatement("SOME AWESOME SQL");
//lots of lines of code that masks the problem
stmt = con.prepareStatment("DIFFERENT SQL"); //You just leaked "SOME AWESOME SQL"!!!
//lots more code
} finally {
stmt.close() //looks like everything is ok, but only the second one actually got closed
}发布于 2013-08-07 07:15:24
我也遇到过同样的问题。虽然阿菲的泄密可能是问题所在,但这不是我的问题,经过一番挖掘,我找到了一个不同的答案:
Oracle JDBC驱动程序维护缓冲区,将数据读入其中作为性能优化。缓冲区大小是根据最大可能的行大小计算的(因此VARCHAR(2000)将分配类似于2000 char的东西),乘以JDBC大小。这允许驱动程序直接将数据读入缓冲区,而不是按需分配(显然)速度较慢。
每个连接中的每条准备好的语句都维护着这类缓冲区。如果您使用的是带有语句缓存的大型连接池(或者您手动缓存PreparedStatement对象,或者泄漏它们.)然后你就可以迅速消耗掉大量的堆空间。在我的情况下1.6GB!
这都是由甲骨文自己在PDF在这里中解释的。
我的经验是基于11.2.0.3的司机。
发布于 2021-01-07 23:12:46
在我的例子中,我找到了这个非常有用的答案,因此,可以通过将DataSource设置Statement Cache Size修改为一个非常小的值来解决这个问题。
我使用的是WebLogic,所以在我的例子中,我将它从默认的10修改为1

原因是因为DataSource本身处理内存中的T4CPreparedStatement对象,因此通过将其简化为一个小值,您就可以避免这个问题。
https://stackoverflow.com/questions/2876895
复制相似问题