java持久性内存泄漏

时间:2011-04-14 14:32:53

标签: java jpa

我在mysql表中有1M行,当我执行以下代码时,我是java持久性api,然后我得到java堆错误:

int counter = 0;
while (counter < 1000000) {
   java.util.Collection<MyEntityClass> data = myQuery.setFirstResult(counter)
       .setMaxResults(1000).getResultList();
   for(MyEntityClass obj : data){
       System.out.println(obj);
   }
   counter += 1000;
}

4 个答案:

答案 0 :(得分:7)

我想知道当您单击“下一步”时,JTable是否真的挂在所有旧引用上。我不相信这是一个持久性问题。无论你在JTable后面有什么支持数据结构,我都要确保在添加下一批记录之前清除它。这样旧的值可以是GC。

您的JTable不应该有ResultSet。拥有一个从客户端隐藏此类详细信息的持久层会更好。查询一批值(整个数据集),将其从ResultSet加载到数据结构中,并关闭finally块中的ResultSet和Statement。您需要在创建它们的方法范围内关闭这些资源,否则您会遇到麻烦。

答案 1 :(得分:2)

几乎可以肯定的是,你的resultSet对象正在缓存整个结果集,这会为这么大的查询占用大量内存。

我没有像你现在那样重置resultSet上的索引 - 它没有清除缓存的结果,我建议你编写一个查询来检索给定页面的相应行,并在每次页面执行时变化。每次丢弃旧的结果集,以确保你没有缓存任何东西。

根据您使用的数据库,您可以使用rownum伪列(Oracle),row_number()(DB2,MSSQL)函数或limit x offset y语法(MySql)。

答案 2 :(得分:1)

  • 这是Java EE还是Java SE应用程序?
  • 您如何处理您的实体 经理?

实体管理器通常与上下文相关联。在事务期间,您恢复的每个实体都将放在其中,并且它将是所有实体的缓存,当事务提交时,JPA将在上下文中搜索修改并将更改提交到数据库。

这意味着如果您恢复100万行,您的上下文中将有100万个实体,并且在您关闭实体管理器之前它们不会是垃圾回收。

由于您指的是JTable,我只能假设这是一个JSE应用程序。在这种类型的应用程序中,您可以完全控制上下文。在这种类型的应用程序中,上下文与实体管理器之间存在一对一的关系(在Java EE环境中并非总是如此)。

这意味着您可以为每个请求(即事务或对话)创建实体管理器,也可以为应用程序的整个生命周期创建实体管理器。

如果您正在使用第二种方法,那么您的上下文永远不会被垃圾收集,并且您从数据库中读取的对象越多,它就越大,直到您最终可能遇到类似您描述的内存问题。

我不是说这是你问题的原因,但它确实是找到根本原因的良好领导,你不觉得吗?

答案 3 :(得分:0)

在他的特定情况下,看起来你的resultSet不适用于GC。检查你的代码,看看这个resultSet的链接到底发生了什么,以便发生内存泄漏。