假设我有一个从数据库加载的对象流(使用Spring Data JPA,如下所示)

public interface MyJpaRepository extends JpaRepository {

  Stream findAll();
}

假设有数百万个Foo对象存储在我的数据库中,使用的GB比我的最大堆内存大小大得多。

我期望通过如下方式使用流,当从数据库加载更多的对象时,JVM可以通过垃圾收集处理过的对象来正确地处理它的堆内存:

try (Stream fooStream =
    myJpaRepository.findAll()) {
  fooStream.forEach(entity -> logger.info("Hello !"));
}

但实际上,这段代码会抛出内存不足异常。

  • 在这种情况下,垃圾收集器是如何工作的?
  • 使用forEach消费这个流需要JVM将流中的数据完全加载到内存中(根据我的理解)?

谢谢你

原文
Jeep87c提问于2021-02-18 12:46

3 个回答

Avishek Bhattacharya
回答于2021-02-18 12:53
得票数 1

Java Stream不会从底层数据库获取所有数据。流不存储数据;相反,它们提供来自集合、数组或IO通道等源的数据。通常,这些都是懒惰的评估。所以,当looger.info在每个实体上调用时,stream将从基础数据存储区获取数据并应用命令。因为流只提供了一个迭代器,所以它只需要获取迭代中的下一个数据,而不是整个集合。一旦对其应用了lambda函数,GC就会删除所获取的数据。

页面原文内容由Jeep87c、Avishek Bhattacharya、Steephen提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:https://stackoverflow.com/questions/66253791复制

扫码关注腾讯云开发者

领取腾讯云代金券