在最大堆中分配字节 [] 时出现 Java OutOfMemoryError

标签 java memory memory-management out-of-memory

我想弄清楚为什么我会收到 OOM 错误,即使我正在初始化的字节数组加上当前使用的内存小于最大堆大小 (1000MB)。 就在数组初始化之前,我使用了 373MB 和 117 个空闲空间。当我尝试初始化占用 371MB 的数组时,出现错误。奇怪的是,错误一直存在,直到我为 JVM 分配 1.2G 或更多。

373 + 371 是 744,我应该还有 256MB 空闲,这让我抓狂。 在第二种情况下,使用 920mb 和 117 free 初始化一个 918mb 的数组至少需要 2800mb。

这是 java 功能的一部分吗?如果是这样,是否有解决方法,以便可以在少于 3n 的内存中完成像数组复制操作这样简单的操作? (内存编号来自运行时,最大堆大小由 -Xmx 设置)

test.java:
byte iv[];
iv =new byte[32];
byte key[] = new byte[32];
new SecureRandom().nextBytes(iv);
new SecureRandom().nextBytes(key);
plaintext = FileUtils.readFileToByteArray(new File("sampleFile"));
EncryptionResult out = ExperimentalCrypto.doSHE(plaintext, key, iv);

ExperimentalCrypto.java:
public static byte[] ExperimentalCrypto(byte[] input ,byte[] key, byte[]iv){
if(input.length%32 != 0){
int length = input.length;
byte[] temp = null; 
System.out.println((input.length/32+1)*32 / (1024*1024));
temp=new byte[(input.length/32+1)*32]; // encounter error here

最佳答案

典型的 JVM 实现将 Java 堆分成几个部分,专用于具有特定生命周期的对象。较大数组的分配通常会绕过较年轻对象的阶段,因为这些区域通常较小,以避免不必要的复制。因此,它们将最终进入“老年代”空间,对于 2/3 大小的空间来说并不罕见。当您使用 JVisualVM 时,我建议安装插件 Visual GC,它可以向您显示不同内存区域及其填充状态的实时 View 。

您可以使用-XX:MaxPermSize=...-XX:MaxNewSize=... 启动选项来减少年轻代和永久代的区域大小,因此间接地提高了老年代区域的比例,您的数组将被分配到该区域。

关于在最大堆中分配字节 [] 时出现 Java OutOfMemoryError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19109378/

相关文章:

java - 在 Java 中加载已编译的类并从文件反序列化它的实例

java - 我的 Facebook 应用程序如何将消息发布到墙上?

c++ - 如何处理在 C/C++ 中返回的指向动态内存的指针

go - 最简单的 Go 竞争条件示例?

memory - Redis 如何在我的本地 Apache 服务器上保存数据,即使在重启和完全断电后也是如此?

linux - 我可以使用 malloc 在 mmap 文件上分配内存吗

c++ - Valgrind 无效的读/写列表

java - 在没有 appletviewer 的情况下在浏览器外部查看 java applet

java - 在独立应用程序中使用@Transactional

c - 全局内存状态Ex() (Win32)