我正在试图弄清楚为什么我收到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
答案 0 :(得分:4)
典型的JVM实现将Java堆分成几个专用于具有特定生命周期的对象的部分。较大阵列的分配通常绕过较年轻物体的阶段,因为这些区域通常较小并且避免不必要的复制。因此,他们将最终进入“老一代”空间,其大小为⅔并不罕见。当您使用JVisualVM
时,我建议您安装插件Visual GC
,它可以显示不同内存区域及其填充状态的实时视图。
您可以使用-XX:MaxPermSize=…
和-XX:MaxNewSize=…
启动选项来减少年轻代和永久代的区域大小,从而间接提高分配阵列的旧代区域的比例