用JDBC4PreparedStatement填充Java堆
我在写剧本!2.3使用Akka进行多线程处理的应用程序。每个线程访问一个MySQL数据库并运行一些计算。每次我运行一组这样的任务时,应用程序的内存占用都会增加,这主要是因为用JDBC4PreparedStatement填充Java堆,java,mysql,hibernate,jpa,playframework-2.0,Java,Mysql,Hibernate,Jpa,Playframework 2.0,我在写剧本!2.3使用Akka进行多线程处理的应用程序。每个线程访问一个MySQL数据库并运行一些计算。每次我运行一组这样的任务时,应用程序的内存占用都会增加,这主要是因为JDBC4PreparedStatement对象永远不会消失。运行几次之后,这些对象占用了超过200MB的内存,很快就会产生一个内存不足错误,调用Sytem.gc()根本不会降低它 我正在使用Hibernate 4.3.0进行持久化,在EntityManager上调用clear()也没有帮助,所以并不是说任何地方都存储了持久
JDBC4PreparedStatement
对象永远不会消失。运行几次之后,这些对象占用了超过200MB的内存,很快就会产生一个内存不足错误,调用Sytem.gc()
根本不会降低它
我正在使用Hibernate 4.3.0进行持久化,在EntityManager
上调用clear()
也没有帮助,所以并不是说任何地方都存储了持久化对象。这意味着可能有Statement
对象在某个地方处于打开状态,但我从不直接与Statement
对象或Connection
对象交互,只与JPA的EntityManager
交互
这是MySQL JDBC或JPA的预期行为吗?如何解决此内存泄漏问题?我不确定在哪里寻找解决方案,不确定这是否是由MySQL、JDBC、JPA或Hibernate实现的。或者可能是游戏的方式!处理JPA
编辑 明确地说,我没有使用
连接
或语句
对象,因此没有任何东西可以关闭。下面是一个示例,我从事务中的Play中获取EntityManager
,执行一些操作,然后事务提交
JPA.withTransaction( () -> {
Site site= JPA.em().find(Site.class, siteId);
site.setDomain("www.stackoverflow.com");
});
这是预期的行为。您必须告诉mysql连接返回一个游标,而不是通过设置选择完整的集合:
stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
java.sql.ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(Integer.MIN_VALUE);
根据您的要求,您的特定设置可能会稍有不同,因此可能需要进行一些调整。正如我在问题中提到的,我没有使用任何
语句
或连接
对象;我正在使用JPA接口。我添加了一个编辑来澄清您将不得不使用本机JDBC来避免此位置的JPA行为。您是否检查了相关的SE问题,如和?没有特别看到这些问题。其中的问题只是一次向内存加载太多,而不是任何形式的泄漏。我在处理完持久性缓存后会非常小心地清除它。在这一点上,我甚至经常使用EntityManager.clear()
,以牺牲速度为代价。