Lambda 在无穷无尽的流中使用整数捕获闭包抛出 OutOfMemoryError
Posted
技术标签:
【中文标题】Lambda 在无穷无尽的流中使用整数捕获闭包抛出 OutOfMemoryError【英文标题】:Lambda capturing closure with Integer in endless stream throws OutOfMemoryError 【发布时间】:2021-12-28 16:36:09 【问题描述】:低于 100% 的代码抛出 java.lang.OutOfMemoryError
Set<Integer> set = new HashSet<>();
new Random().ints(10_000_000,
Integer.MIN_VALUE,
Integer.MAX_VALUE)
.forEach(
v ->
if(set.contains(v))
System.out.println(v);
else
set.add(v);
);
AFAIK 这是因为 lambda 捕获带有上下文的整数?谁能解释一下这里到底发生了什么?
【问题讨论】:
你的java版本是多少?我有 openjdk 版本 "11.0.12" 2021-07-20 OpenJDK 运行时环境 Homebrew (build 11.0.12+0) OpenJDK 64-Bit Server VM Homebrew (build 11.0.12+0, 混合模式)。当我使用-Xmx128m
运行此代码时,堆永远不会超过 90mb
对不起,我编辑了代码示例,请尝试
【参考方案1】:
在您的代码中,您有 Set
,可通过 main
方法访问。本地栈是 GC 根,所以不能被 GC 收集。
因此,您正在向集合中添加无法收集的元素。并且 set 需要额外的内存来存储元素。
在我的 PC 上,在没有 OOM 的情况下运行这个程序需要大约 600 MB 的堆空间。
这是在我的电脑上运行的这个程序的堆转储。
我已经用 vanilla for
循环尝试了相同的代码并得到了相同的结果。
所以您只需要为您的应用程序添加更多内存。例如-Xmx1g
会将您的堆大小设置为 1 GB。
【讨论】:
其实我是从单元测试开始的,和main方法一样吗? 是的,从单元测试开始时,您的代码也可以从本地堆栈访问。你可以在你的surefire插件的配置中设置内存设置***.com/a/7579853/4655217以上是关于Lambda 在无穷无尽的流中使用整数捕获闭包抛出 OutOfMemoryError的主要内容,如果未能解决你的问题,请参考以下文章