V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
MartinDai
V2EX  ›  Java

为什么这样的堆内存会 OOM

  •  
  •   MartinDai · 2017-02-13 17:51:50 +08:00 · 3199 次点击
    这是一个创建于 2841 天前的主题,其中的信息可能已经有所发展或是发生改变。
    Heap Configuration:
       MinHeapFreeRatio = 40
       MaxHeapFreeRatio = 70
       MaxHeapSize      = 1073741824 (1024.0MB)
       NewSize          = 1310720 (1.25MB)
       MaxNewSize       = 17592186044415 MB
       OldSize          = 5439488 (5.1875MB)
       NewRatio         = 2
       SurvivorRatio    = 8
       PermSize         = 157286400 (150.0MB)
       MaxPermSize      = 157286400 (150.0MB)
    
    Heap Usage:
    PS Young Generation
    Eden Space:
       capacity = 19922944 (19.0MB)
       used     = 19911792 (18.989364624023438MB)
       free     = 11152 (0.0106353759765625MB)
       99.94402433696546% used
    From Space:
       capacity = 12517376 (11.9375MB)
       used     = 0 (0.0MB)
       free     = 12517376 (11.9375MB)
       0.0% used
    To Space:
       capacity = 13303808 (12.6875MB)
       used     = 0 (0.0MB)
       free     = 13303808 (12.6875MB)
       0.0% used
    PS Old Generation
       capacity = 715849728 (682.6875MB)
       used     = 715848480 (682.6863098144531MB)
       free     = 1248 (0.001190185546875MB)
       99.99982566173442% used
    PS Perm Generation
       capacity = 157286400 (150.0MB)
       used     = 79364440 (75.68782806396484MB)
       free     = 77921960 (74.31217193603516MB)
       50.45855204264323% used
    

    明明内存还有空余的,为什么不继续扩展EdenSurvivor区呢,另一台一样配置的机器 OOM 的时候是这样的:

    Heap Configuration:
       MinHeapFreeRatio = 40
       MaxHeapFreeRatio = 70
       MaxHeapSize      = 1073741824 (1024.0MB)
       NewSize          = 1310720 (1.25MB)
       MaxNewSize       = 17592186044415 MB
       OldSize          = 5439488 (5.1875MB)
       NewRatio         = 2
       SurvivorRatio    = 8
       PermSize         = 157286400 (150.0MB)
       MaxPermSize      = 157286400 (150.0MB)
    
    Heap Usage:
    PS Young Generation
    Eden Space:
       capacity = 119341056 (113.8125MB)
       used     = 119253176 (113.72869110107422MB)
       free     = 87880 (0.08380889892578125MB)
       99.92636230736889% used
    From Space:
       capacity = 111869952 (106.6875MB)
       used     = 0 (0.0MB)
       free     = 111869952 (106.6875MB)
       0.0% used
    To Space:
       capacity = 111149056 (106.0MB)
       used     = 0 (0.0MB)
       free     = 111149056 (106.0MB)
       0.0% used
    PS Old Generation
       capacity = 715849728 (682.6875MB)
       used     = 715849720 (682.6874923706055MB)
       free     = 8 (7.62939453125E-6MB)
       99.99999888244702% used
    PS Perm Generation
       capacity = 157286400 (150.0MB)
       used     = 110605624 (105.48174285888672MB)
       free     = 46680776 (44.51825714111328MB)
       70.32116190592448% used
    

    这台看起来就比较正常,内存是真的用完了

    求解第一台 OOM 的原因

    10 条回复    2017-02-13 20:53:06 +08:00
    kiddult
        1
    kiddult  
       2017-02-13 18:10:43 +08:00
    两个 Eden 和 Old Generation 都满了
    ArcherFeel
        2
    ArcherFeel  
       2017-02-13 18:30:21 +08:00
    1) Eden -> From/To
    ArcherFeel
        3
    ArcherFeel  
       2017-02-13 18:36:06 +08:00
    1) Eden -> From/To
    2) From/To -> Old

    From/To 都是空的, 所以不是 2)的情形;
    Eden 已经满了, 所以 new 的对象没有可以空间了.

    不过不明白为什么 Eden 都满了, 既没有被 Minor GC 回收也没有移到 From/To. 搭车同问

    也许对象不是 new 出来的(而是内存拷贝什么的), 所以可能适用于 2)的情况? 这种是我猜的 - -
    HunterPan
        4
    HunterPan  
       2017-02-13 19:00:30 +08:00
    内存回收也需要的空间的,没有多余的 eden ,没办法回收吧
    Accldent
        5
    Accldent  
       2017-02-13 19:10:11 +08:00
    目测第一个 OOM 是因为 young GC 的时候, Eden 区的存活对象太多, S0 、 S1 不够存放,需要 Old 区作担保,但是 Old 区已满,触发 full GC , full GC 完了空间还是不够( old 区没有空余内存空间),抛出 OOM 。

    做个 heapdump 看下是不是有大对象被 reference 住不能释放(比如 collection 的生命周期太长,只加不减
    MartinDai
        6
    MartinDai  
    OP
       2017-02-13 20:10:14 +08:00
    @Accldent 那为什么 Eden 区不扩展呢 第二个的 eden 区都扩展到 100+M 了
    MartinDai
        7
    MartinDai  
    OP
       2017-02-13 20:11:52 +08:00
    @kiddult 但是分配的内存还没用完,完全可以先扩展到上限,再不够的时候再 OOM 啊
    MartinDai
        8
    MartinDai  
    OP
       2017-02-13 20:12:18 +08:00
    @HunterPan Eden 为什么不扩展获得更大的空间呢
    mind3x
        9
    mind3x  
       2017-02-13 20:46:49 +08:00 via Android
    @MartinDai 推测是你第一台机器上系统已无可用 ram 分配给 JVM 。虽然 JVM 开关是最大 1G heap , OS 不够分也没办法。
    zacard
        10
    zacard  
       2017-02-13 20:53:06 +08:00
    为什么 xmx 和 xms 不设置为一样?就没有内存扩展不扩展的问题了。
    old gen 都满了。程序上肯定有问题。

    内存溢出的情况比较多啊。
    例如:
    ( 1 )可能是 yong gen 中的对象挨要晋升 到 old gen ,结果没有空间了。 full gc 后 old gen 收不回,就 oom 了
    ( 2 )也有可能是你直接分配一个大对象,默认直接放到 old gen ,结果 old gen 放不下, full gc 后 old gen 收不回,就 oom----个人猜测是这种
    等等。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5665 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 98ms · UTC 09:04 · PVG 17:04 · LAX 01:04 · JFK 04:04
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.