【问题标题】:JDBC Connection Pool Memory Issues (Java EE Application)JDBC 连接池内存问题(Java EE 应用程序)
【发布时间】:2012-10-19 07:04:24
【问题描述】:

我目前有一个 Java EE 应用程序,我在其中实现了自己的连接池类。我使用的每种方法都执行一个简单的查询(Statement 和 ResultSet)。在我使用 JDBC/my pool 的每个方法的 finally 块中,我首先关闭 ResultSet,然后关闭 Statement,因为书籍和网上指示应该做的很多很多资源。最后,我将连接返回到池中。

在查看 JVM 的内存时,我注意到在我通过连接池使用 JDBC 进行调用后,内存从未真正释放,或者需要很长时间才能释放。我检查了我的垃圾收集设置,我正在使用 gencon (IBM WebSphere),许多在线资源都表明它也非常好。我也在我的应用程序中使用 Spring Framework。

我写的连接池类很简单。初始化后,它会创建一定数量的数据库连接并将它们添加到队列中(我尝试了另一种仅使用简单向量的实现,但与内存的结果相同)。当您请求连接时,它会检查以确保有可用的连接,如果有,它会向调用者提供一个。最后,您将其返回并放回队列/向量中。

我想知道是否还有其他可以解决的办法?我应该让 Spring Framework 来处理我的连接池,还是有其他东西可以更好地处理内存?对我来说,这确实有意义,但我对实现连接池不太熟悉。所有资源都说要做我正在做的事情,但我假设他们可能正在使用一些内置的池实现。我确实知道关闭连接是可行的,但由于这是一个自定义池解决方案,我不能真正做到这一点。

谢谢!

【问题讨论】:

  • 绝对使用现有的池实现,绝对让 Spring 为您处理。你正在重新发明轮子。

标签: java memory jdbc jvm


【解决方案1】:

您的应用程序是否在 WebSphere 应用程序服务器中运行?它是从应用服务器获取它的数据源,而不是自己创建它吗?如果是这样,那么连接和语句已经被池化了,你不需要自己去池化它们。

【讨论】:

  • +1 用于提及 WebSphere 的内置连接池。在我的回答中完全忘记了它......
  • 应用程序在 WAS 内部运行,是的。我不确定数据源是否来自应用服务器本身,但我不这么认为。正在这样创建连接: Class.forName("com.ibm.db2.jcc.DB2Driver"); connection = DriverManager.getConnection(jdbcURL, username, pass);
  • 这是在容器下使用 JDBC 的糟糕方式。您的 WebSphere 配置中是否有 JDBC 驱动程序定义?和数据源定义?
  • 我同意。有 JDBC 驱动程序定义,但没有数据源定义。我将添加数据源定义并以这种方式实现它。看起来好多了。
  • 我使用 WAS 的内置连接池实现了它。那是我最后一次跟随某人使用自定义池解决方案。当然,内置池似乎效果更好。
【解决方案2】:

好的,第一件事是第一件事:除非你有很好的理由,否则实施你自己的连接池机制是一种不必要的风险练习。那里有许多连接池机制可供选择 - Spring 将是其中之一,Jakarta 的 DBCP 是另一个。如果您可以选择使用第三方实用程序进行连接池 - 请执行此操作。如果您在容器中运行,让容器为您完成工作(WebSphere 已经通过它的各种“帮助类”完成了这项工作)。

关于您遇到的症状:内存未释放的事实并不意味着存在内存泄漏。由 JVM 决定是否以及何时真正释放未引用的对象实例。您是否也遇到 OutOfMemory 错误?

首先发出一些堆转储(在 JDBC 资源发布之后)以查看其中发生了什么。

关于您编写​​的代码——不发布代码,很难猜测您是否有隐藏的错误;但是您描述的流程似乎是正确的。

【讨论】:

  • 我就是这么想的。我进入这个代码库不是原作者。其他地方使用了自定义 JDBC 池机制(不知道原作者为什么这样做。代码中有一条评论“不幸的是我们不能为此使用 Spring”,但我不确定为什么会这样)。我按照他的惯例也照做了)。好吧,我知道这不是内存泄漏(从技术上讲,Java 中不存在内存泄漏之类的东西,对吧?;-)),但它是“内存消耗”。我们的设置很高,但是很久以前我们遇到过内存不足的问题。
  • 一句古老的土耳其谚语说:“无论你走错多远,都要回头。”
  • 我很高兴这是土耳其谚语。我将在 Spring 中实现它,希望它会起作用。代码中有一条注释说 Spring 不起作用或类似的东西,但谁知道他们是否正确实现了它。
  • 我可以看到您正在使用 WebSphere。如果你在容器下运行,绝对不要使用任何连接池(甚至 Spring 也不行); WebSphere 维护自己的连接池机制。您所要做的就是从DataSource 获取连接,使用它并在最后释放它。
猜你喜欢
  • 1970-01-01
  • 2011-04-01
  • 2012-02-28
  • 2011-10-24
  • 1970-01-01
  • 1970-01-01
  • 2011-10-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多