为何选择OOM?并且首先gc为什么Tenured:8192K-> 8961K(10240K)?

时间:2017-08-23 03:05:39

标签: java out-of-memory

我的代码:

public class TestJVmRiZHI{   
/**
 jdk 1.8
 -XX:+UseSerialGC
 -verbose:gc
 -Xms20M
 -Xmx20m
 -Xmn10M
 -XX:+PrintGCDetails
 -XX:SurvivorRatio=8
 * @param args
 */     

  private  static final int _1mb = 1024 * 1024;
  public static void main(String[] args) {
    Byte[] allocation1 = new Byte[2*_1mb];
    Byte[] allocation2 = new Byte[2*_1mb];
    Byte[] allocation3 = new Byte[2*_1mb];
    Byte[] allocation4 = new Byte[4*_1mb];
  }
}

结果:

  

线程“main”中的异常java.lang.OutOfMemoryError:Java堆空间       在controller.TestJVmRiZHI.main(TestJVmRiZHI.java:24)

     

[GC(分配失败)[DefNew:2540K-> 770K(9216K),0.0034872 secs]

     

[终身:8192K-> 8961K(10240K),0.0071963秒] 10732K-> 8961K(19456K),

     

[Metaspace:3385K-> 3385K(1056768K)],0.0107478 secs] [次:用户= 0.01 sys = 0.00,real = 0.01 secs]

     <完全GC(分配失败)[终身:8961K-> 8943K(10240K),0.0073261秒] 8961K-> 8943K(19456K),[Metaspace:3385K-> 3385K(1056768K)],0.0073536秒] [时间:用户= 0.02 sys = 0.00,实际= 0.01秒]

     

堆    def新一代总计9216K,使用410K [0x00000000fec00000,0x00000000ff600000,0x00000000ff600000]

     

伊甸园空间8192K,5%使用[0x00000000fec00000,0x00000000fec66800,0x00000000ff400000]

     

来自空间1024K,0%使用[0x00000000ff500000,0x00000000ff500000,0x00000000ff600000]

     

到空间1024K,0%使用[0x00000000ff400000,0x00000000ff400000,0x00000000ff500000]

     

终身代总计10240K,使用8943K [0x00000000ff600000,0x0000000100000000,0x0000000100000000]

     

空间10240K,87%使用[0x00000000ff600000,0x00000000ffebbd38,0x00000000ffebbe00,0x0000000100000000)

     

Metaspace使用3429K,容量4494K,承诺4864K,保留1056768K

     类空间使用382K,容量386K,承诺512K,保留1048576

1 个答案:

答案 0 :(得分:0)

Byte[]是一个对象引用数组。

对象引用通常是4个字节。在具有超过32 GB堆的64位计算机上,对象引用为8个字节。

因此,假设4个字节,2 * 1024 * 1024 * 4 = 8 MB

所以:

allocation1:  8 MB
allocation2:  8 MB
allocation3:  8 MB
allocation4: 16 MB
             =====
      total: 40 MB

只有-Xmx20m内存不足。

您可能希望new Byte[2*_1mb]分配2 MB,因此Byte更改为byte ,因此数组是基元数组{{1} }值,而不是对象引用数组。