繁体   English   中英

Java持久性内存泄漏

[英]java persistance memory leaks

我在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;
}

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

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

问题几乎可以肯定是您的resultSet对象正在缓存整个结果集,这样的大型查询会占用大量内存。

我建议您编写一个查询以检索给定页面的适当行,并在每次页面更改时执行该查询,而不是像现在那样在resultSet上重置索引-这不会清除缓存的结果。 每次都删除旧的结果集,以确保您不缓存任何内容。

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

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

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

这意味着,如果您恢复100万行,则在上下文中将有100万个实体,并且在关闭实体管理器之前将无法回收这些实体。

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

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

如果使用第二种方法,则永远不会垃圾收集上下文,并且从数据库中读取的对象越多,对象就越大,直到最终遇到与您所描述的内存有关的问题。

我并不是说这是造成您问题的原因,但肯定可以找到根本原因,您认为吗?

看起来您的resultSet在特定情况下不受GC约束。 检查您的代码,然后查看到此resultSet的链接的实际位置,以便发生内存泄漏。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM