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

373 + 371是744,我应该仍然有256MB可用空间,这让我发疯了。
在第二种情况下,使用920mb和117自由初始化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堆分成若干段,这些段专用于具有一定生存期的对象。较大阵列的分配通常绕过年轻对象的阶段,因为这些区域通常较小,以避免不必要的复制。因此,它们最终将进入“老一代”空间,对于这种空间,⅔的大小并不罕见。当您使用JVisualVM时,我建议安装插件Visual GC,该插件可以向您显示不同内存区域及其填充状态的实时视图。

您可以使用-XX:MaxPermSize=…-XX:MaxNewSize=…启动选项来减少年轻一代和永久一代的区域大小,从而间接增加要分配阵列的老一代区域的一部分。

10-07 18:59
查看更多