Java持久性内存泄漏

| 我在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;
}
    
已邀请:
我想知道,当您单击\“ next \”时,JTable是否真的挂在了所有那些旧引用上。我不认为这是一个持久性问题。无论JTable背后有什么支持的数据结构,我都必须确保在添加下一批记录之前先将其清除。这样,旧值可以被GC \。 您的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的链接的实际位置,以便发生内存泄漏。     

要回复问题请先登录注册