【发布时间】:2015-10-19 07:51:08
【问题描述】:
在我的应用程序中,我有几千个轻量级对象(我想将它们保存在内存中)。每个轻量级对象都引用一个重数据对象,如果堆已满,我希望按需加载并收集垃圾(并再次按需重新加载)。所以使用 JPA 我做了类似的事情,
public class LightWeight{
@OneToOne(fetch = FetchType.LAZY)
private HeavyWeight data;
....
}
第一次使用 FetchType.LAZY 加载 HeavyWeight 时效果很好,但不幸的是,由于 HeavyWeight 是一个正常的引用,它永远不会被垃圾收集,因此我在一段时间后内存不足。
是否有一种 JPA 机制可以进行延迟获取,如果堆满时“卸载”(如 WeakReference)并在需要时再次重新获取引用?
顺便说一句:我在 Hibernate 上使用 Spring Data JPA 作为实现。
更新 1: 考虑到关于使用二级缓存的评论,那么依赖缓存并在获取重量级对象后立即分离它们呢? IE。像这样的......
public class LightWeight{
int heavyWeightId = ...;
@Autowired
HeavyWeightRepository heavyWeightRepository;
public HeavyWeight getData(){
HeavyWeight hv = heavyWeightRepository.findById(id);
heavyWeightRepository.detach(hv); //using custom repository
return hv;
}
}
在这种情况下,HeavyWeight 对象一旦从 EntityManager 中分离出来就应该被垃圾回收(并且不会从其他任何地方引用),这是正确的吗?
更新 2:我放弃了使用 SoftReferences 的想法。主要问题是,尽管通过显式清除 EM 或提交事务来释放实体管理器对托管对象持有的所有引用应该允许仅由软引用引用的实体被垃圾收集,以防内存变得稀疏,但它不起作用在实践中,经常会遇到“超出 GC 开销限制”的问题。所以要走的路是使用cmets中建议的二级缓存。
【问题讨论】:
-
最好使用经过适当测试的解决方案,例如ehCache,而不是尝试编写自己的解决方案。
-
好的。以及如何确保“HeavyWeight”对象被垃圾收集?取出后立即拆下它们?
标签: java hibernate jpa garbage-collection spring-data-jpa