代码之家  ›  专栏  ›  技术社区  ›  Jay

Oracle T4CPrepareStatement内存泄漏?

  •  5
  • Jay  · 技术社区  · 15 年前

    我将在下面几行中讨论的应用程序的一些背景:

    XYZ 是一个数据屏蔽工作台EclipseRCP应用程序:为它提供一个源表列和一个目标表列,它将应用一个转换(encryption/shuffling/etc),并将行数据从源表复制到目标表。现在,当我一次屏蔽n个表时,这个应用程序会启动n个线程。

    问题是:

    我在第一次推出上述应用程序时遇到了一个生产问题。不幸的是,我没有任何日志可以访问根目录。但是,我尝试在测试区域运行这个应用程序并进行压力测试。

    当我收集.hprof文件并通过分析器(yourkit)运行它们时,我注意到oracle.jdbc.driver.t4cpreparestatement的对象正在保留堆。分析还告诉我,我的一个类正在保存对这个PreparedStatement对象的引用,因此,n个线程有n个这样的对象。t4cpreparestate似乎有字符数组:lastboundchars和bindchars,每个大小为char[300000]。

    所以,我研究了一下(谷歌!),获取了ojdbc6.jar并尝试对t4cpreparestation进行反编译。我看到t4cprepareStatement扩展了oraclePreparedStatement,它动态地管理lastBoundChars和bindChars的数组大小。

    所以,我的问题是:

    1. 你有没有遇到过这样的问题? 这个?
    2. 你知道 最后一个boundchars/bindchars?
    3. 我是个新手,你也是 你觉得我做得不对吗?(i 还通过垫子运行hprofs- 这是主要的 问题-所以,我不认为我 可能是错的?)

    我在网上发现了类似的东西: http://forums.oracle.com/forums/thread.jspa?messageID=2860681

    感谢您的建议/建议。

    2 回复  |  直到 15 年前
        1
  •  9
  •   Affe    15 年前

    虽然可能,但您似乎不太可能在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
    }
    
        2
  •  14
  •   Tim Gage    12 年前

    我遇到了同样的问题。虽然问题可能出在阿菲身上,但这不是我的问题,我在挖掘之后找到了一个不同的答案:

    OracleJDBC驱动程序维护缓冲区,将数据作为性能优化读取到缓冲区中。缓冲区大小是根据可能的最大行大小计算的(因此 VARCHAR(2000) 会分配大约2000个 char s),乘以JDBC获取大小。这允许驱动程序直接将数据读取到缓冲区,而不是按需分配(显然)速度较慢。

    每个连接中的每个准备好的语句都维护一个此类缓冲区。如果使用带有语句缓存(或缓存)的大型连接池 PreparedStatement 对象是手动的,或者泄漏它们…)然后您可以迅速占用大量堆空间。我的情况是1.6GB!

    这一切都是由甲骨文自己在 PDF here

    我的经验是基于11.2.0.3司机。