在我的应用程序中,我使用Eclipselink v2.5.2作为JPA提供程序。在Weblogic v12.1.3和Java 8中运行。
每天晚上都要完成一项大任务,我的应用程序会在数据库中查询一整天的数据(在Java对象中大约200 MB),
JPA不应缓存此数据。所有涉及的实体都有@Cacheable(false)
注释。
为了处理这些数据,还要从数据库中获取一些配置,这些实体和查询结果应该由eclipselink缓存。
到期时间为1分钟,缓存类型为SOFT_WEAK。这意味着当内存不足时,可以相对快速地清除缓存。 Eclipselink中的共享缓存模式全局设置为DISABLE_SELECTIVE
大型任务由无状态EJB执行,数据和配置在一个事务中从数据库中检索,但是由不同的
无状态EJB,由Weblogic注入自己的EntityManager
(使用相同的@PersistenceContext
)。
对于针对数据库执行的速度和查询,缓存按预期工作。
但是,在进一步查看应用程序的内存使用情况时,
我注意到在每日任务之后,使用的内存量大约高200mb,并且通过强制此任务连续运行几次(超过1分钟),
我可以让应用程序耗尽内存(并最终抛出OutOfMemoryError
)。
在注意到这一点之后,我检查了一个堆转储(见截图),并确认Eclipselink正在阻止垃圾收集器收集大数据集。 我将这个heapdump解释如下(红色添加是我使用Eclipse Memory Analysis的结论,' inspect' window):
在我的示例中,我运行了3次大型任务,这将导致相同数据的3倍(大集和配置)。 Eclipselink保持每次运行的完整副本。
我发现调用entityManager.getEntityManagerFactory().getCache().evictAll();
会清理这些数据。我怀疑只清除这里涉及的查询的缓存也会这样做。
我想知道为什么Eclipselink会保留大数据集。有没有我做错了,或者这是Eclipselink中的一个错误?
此外,我想知道Eclipselink何时会清理这些数据,当我的初始尺寸为'是否已达到查询,或者是否会更早清除?