Java大二维数组触发java.lang.OutOfMemoryError问题排查
大数组初始化触发OutOfMemoryError的原因解析
连续内存块分配失败
当创建char[][] buffer这类超大二维数组时,JVM需要为其分配连续的内存区域。即使设置的-Xmx足够,堆内存也可能因为碎片化问题,没有一块足够大的连续空闲空间来容纳这个数组。DIM=5时12GB的数组能分配成功,只是刚好当时堆里有足够的连续空间;当DIM≥6时,所需的连续内存块更大,碎片化的堆无法满足需求,直接触发OOM。实际内存开销超出理论计算值
你计算的DIM * GB * 2字节只是char元素的内存,但二维数组是“数组的数组”——每个子数组都是独立对象,每个对象会额外占用对象头(约16字节)和数组长度字段的内存。当DIM很大时,这些额外开销会累积。再加上JVM自身的内存占用(元空间、线程栈、直接内存等),实际需要的总内存远高于理论值,可能直接逼近-Xmx上限。JVM内存区域的叠加占用
-Xmx只是堆内存的最大值,JVM运行还需要非堆内存(比如存储类元数据的元空间、代码缓存等),这些也会占用系统的48GB内存。如果-Xmx设到40GB左右,加上非堆内存的开销,系统可用内存会被耗尽,JVM无法为堆申请到足够空间,自然无法分配超大数组。GC无法整理出足够连续空间
虽然JVM在OOM前会触发垃圾回收,但GC只能清理无用对象、整理碎片化内存,却无法保证能整理出足够大的连续块来容纳超大对象。如果程序在初始化数组前已经创建了大量存活对象,堆的可用空间会被分割成多个小块,GC后也无法合并出满足需求的连续区域。
内容的提问来源于stack exchange,提问作者Enrypase
相关产品推荐
相关产品推荐

