【问题标题】:SoftReferences for JPAJPA 的软引用
【发布时间】: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


【解决方案1】:

正如 ghdalum 已经指出的,Weak 或 SoftReferences 是在纯 Java 中处理此 GC 问题的正确方法。

关于 JPA,我看到了另外两个可能的问题:

  1. 持久性提供程序的缓存(他们也可能使用 SoftReferences)
  2. 保持由您的持久性上下文管理的实体

1

您是否尝试将 javax.persistence.sharedCache.mode 设置为 DISABLE_SELECTIVE 并在 HeavyWeight 类上设置 @Cacheable(false)

您也可以尝试手动清除缓存,例如

javax.persistence.Cache c = myEntityManagerFactory.getCache()
c.evict(heavyWeight)  // does not clear heavyWeight.references

2

  • 分离实体或
  • 关闭EntityManager

如果可能,我会选择性地禁用缓存并让 LightWeight 返回 HeavyWeight 的副本,这样您就可以完全控制其生命周期(例如,使用缓存)。另一个想法是在需要时使用JPQL Constructor Expressions 获取HeavyWeights 数据的副本。

【讨论】:

  • 感谢您的评论 (+1)。关于 1:我现在使用 springs 缓存抽象和 ehcache 作为二级缓存,这样做我设法实现了我试图使用软引用获得的行为。关于 2:根据我的观察,分离实体仅在事务完成后才可用于 gc。因为我找不到任何关于这种行为的文档,所以我宁愿不依赖它....
【解决方案2】:

我自己还没有尝试过,但是如何实现一个 JPA attribute converter 在加载时将重数据对象转换为 WeakReference。

对于这个用例来说,WeakReference 可能看起来很弱,也许 SoftReference 更好?

【讨论】:

  • 你是绝对正确的,WeakReference 是无用的,SoftReference 将是要走的路......不幸的是,使用它们我遇到了“GC 开销限制超出问题”......正在考虑使用提议的 ehcache...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-26
  • 1970-01-01
  • 2020-02-05
  • 2011-02-09
  • 1970-01-01
  • 2016-04-26
相关资源
最近更新 更多