在达到堆的最大值 space 之前出现 OutOfMemoryError?
OutOfMemoryError before reaching the maximum of the heap space?
我遇到了一个非常奇怪的问题,我想在 SSCCE 中重现,但我不能。
我运行使用 -Xmx1024m
在 Java8(32 位)中设置我的程序,这段代码使用 [=120MB 将一个相当大的文件(120MB)加载到一个字节数组中=12=].
问题是,在 Java6 中我没有遇到任何问题,在 Java8 中,我一尝试加载它就得到 OutOfMemoryError
异常。
我还有很多空闲内存,我已经对其进行了分析,我发现没有问题。
如果我尝试在 SSCCE 中找出这个问题,那么它就成功了。
我知道 Oracle 已经摆脱了 PermGen,但这对我的程序有何影响?
我还读到它可能与堆的碎片问题有关 space,但我尝试调试它、分析它,并且 运行 一个来自分析器的 GC 周期在分配内存之前,它仍在发生(我假设 GC 循环会对堆进行碎片整理 space)
在 Java8 中,有一些新的东西被移到了堆上,这些东西以前是 PermGen 空间的一部分,例如字符串池,还要检查它分配的老年代的大小
几件事。
- 1 GB 并不多,即使在 Windows 32 位上你也可以达到 1400 MB。
- Java 8 与 Java 6 的工作方式不同,它是在内存比 9 年前发布 Java 6 时更便宜的假设下优化的。
- 您可以将内存映射到 120 MB 并且根本不使用堆。然而,这可能是一种更有效的方法
- 消耗的内存几乎可以肯定是您对可能是文件大小许多倍的数据所做的操作。我不会假设您实际上只使用 120 MB 来处理这个文件。
我建议您对内存充足的应用程序进行内存分析,如果您必须了解内存消耗的位置,请使用呃 64 位 JVM。
我想我找到原因了。根据此错误报告:
https://bugs.openjdk.java.net/browse/JDK-6478546
FileInputStream
将 space 直接保留到本机内存中。增加最大堆 space 的大小时实际上更糟,因为原生地图实际上更少 space。
我的代码使用 Java8 64 位的原因正是因为我有更多来自 Windows 的虚拟 space,而不是 [=31] 中的 ~1.7Gb =].
我仍然不是很清楚为什么相同的代码在 Java6 中有效。似乎相同的应用程序在 Java8 中使用的本机 space 比在 Java6 中使用的更多。也许 Metaspace 的新方案稍微改变了一些事情。我不确定。
关于它的有趣文章:
http://www.codingthearchitecture.com/2008/01/14/jvm_lies_the_outofmemory_myth.html
我遇到了一个非常奇怪的问题,我想在 SSCCE 中重现,但我不能。
我运行使用 -Xmx1024m
在 Java8(32 位)中设置我的程序,这段代码使用 [=120MB 将一个相当大的文件(120MB)加载到一个字节数组中=12=].
问题是,在 Java6 中我没有遇到任何问题,在 Java8 中,我一尝试加载它就得到 OutOfMemoryError
异常。
我还有很多空闲内存,我已经对其进行了分析,我发现没有问题。
如果我尝试在 SSCCE 中找出这个问题,那么它就成功了。
我知道 Oracle 已经摆脱了 PermGen,但这对我的程序有何影响?
我还读到它可能与堆的碎片问题有关 space,但我尝试调试它、分析它,并且 运行 一个来自分析器的 GC 周期在分配内存之前,它仍在发生(我假设 GC 循环会对堆进行碎片整理 space)
在 Java8 中,有一些新的东西被移到了堆上,这些东西以前是 PermGen 空间的一部分,例如字符串池,还要检查它分配的老年代的大小
几件事。
- 1 GB 并不多,即使在 Windows 32 位上你也可以达到 1400 MB。
- Java 8 与 Java 6 的工作方式不同,它是在内存比 9 年前发布 Java 6 时更便宜的假设下优化的。
- 您可以将内存映射到 120 MB 并且根本不使用堆。然而,这可能是一种更有效的方法
- 消耗的内存几乎可以肯定是您对可能是文件大小许多倍的数据所做的操作。我不会假设您实际上只使用 120 MB 来处理这个文件。
我建议您对内存充足的应用程序进行内存分析,如果您必须了解内存消耗的位置,请使用呃 64 位 JVM。
我想我找到原因了。根据此错误报告:
https://bugs.openjdk.java.net/browse/JDK-6478546
FileInputStream
将 space 直接保留到本机内存中。增加最大堆 space 的大小时实际上更糟,因为原生地图实际上更少 space。
我的代码使用 Java8 64 位的原因正是因为我有更多来自 Windows 的虚拟 space,而不是 [=31] 中的 ~1.7Gb =].
我仍然不是很清楚为什么相同的代码在 Java6 中有效。似乎相同的应用程序在 Java8 中使用的本机 space 比在 Java6 中使用的更多。也许 Metaspace 的新方案稍微改变了一些事情。我不确定。
关于它的有趣文章:
http://www.codingthearchitecture.com/2008/01/14/jvm_lies_the_outofmemory_myth.html