当虚拟机申请不到内存空间的时候,会报堆内存溢出: OutOfMemoryError:java heap space 。
常见的原因: http://outofmemory.cn/c/java-...
我测试到时候,运行在 16G 内存的机器上。JVM 堆内存 默认为物理内存的1/4,即 16 * 1/4 = 4G
JDK 8的 JVM 在 JDK 7 的基础上从堆内存中移除了 永久代(Perm Generation) ,替换为了堆内存之外的 元空间(Metaspace) ,元空间是堆外直接内存,不受堆内存的限制,只受物理内存的限制,可以提供更大的空间。
OutOfMemoryError异常的常见原因:
/**java堆溢出实例 * 原理:java的堆是用来存放对象实例的,所以我们只要做到以下三点就可以使堆溢出: * 1、限制堆的大小,不可扩展 * 2、不断新建对象 * 3、保持对象存活不被回收 * 对应的,我们需要: * 1、改变JVM的启动参数,将堆的最小值和最大值设成一样,这样就可以避免堆自动扩展(其实不一样也可以) * 2、不断产生对象 * 3、使用一个List来保存对象,保持对象存活 * * JVM配置参数: -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError * */ public class HeapOom { public static void main(String[] args) { // 此list实例会存放在堆内存中 List<byte[]> list = new ArrayList<>(); int i = 0; boolean flag = true; while (flag) { try { i++; // 每次增加一个1M大小的数组对象 list.add(new byte[1024 * 1024]); } catch (Throwable e) { // catch 捕获的是 Throwable,而不是 Exception。因为 OutOfMemoryError 不属于 Exception 的子类。 e.printStackTrace(); flag = false; // 记录次数 System.out.println("count=" + i); } } // 不让进程结束,便于使用分析工具来查看内存情况 try { Thread.sleep(24 * 60 * 60 * 1000); } catch (InterruptedException e) { e.printStackTrace(); } } }
使用的 java 1.8.0_171 版本:
$ java -version java version "1.8.0_171" Java(TM) SE Runtime Environment (build 1.8.0_171-b11) Java HotSpot(TM) 64-Bit Server VM (build 25.171-b11, mixed mode)
报错信息:
count=3316 java.lang.OutOfMemoryError: Java heap space at com.song.HeapOom.main(HeapOom.java:21)
运行结果表明,运行到 3316 次时,出现了 堆内存溢出 。由于每次增加1M内存。粗略估计:程序大约使用3G内存时,出现了内存溢出情况。
通过jmap或VisualVM 者工具可以查看内存情况:最后可以看出,老年代内存使用情况,大约使用了2709MB,使用率近100%。从而导致了 OutOfMemoryError
TIPS:下面查看内存时,由于使用工具查看内存的时间不是同一时间,所以内存使用量有细微差别
$ jmap -heap 3428 Attaching to process ID 3428, please wait... Debugger attached successfully. Server compiler detected. JVM version is 25.66-b18 using thread-local object allocation. Parallel GC with 4 thread(s) Heap Configuration: MinHeapFreeRatio = 0 MaxHeapFreeRatio = 100 MaxHeapSize = 4261412864 (4064.0MB) NewSize = 88604672 (84.5MB) MaxNewSize = 1420296192 (1354.5MB) OldSize = 177733632 (169.5MB) NewRatio = 2 SurvivorRatio = 8 MetaspaceSize = 21807104 (20.796875MB) CompressedClassSpaceSize = 1073741824 (1024.0MB) MaxMetaspaceSize = 17592186044415 MB G1HeapRegionSize = 0 (0.0MB) Heap Usage: PS Young Generation Eden Space: capacity = 637009920 (607.5MB) used = 637009920 (607.5MB) free = 0 (0.0MB) 100.0% used From Space: capacity = 11010048 (10.5MB) used = 0 (0.0MB) free = 11010048 (10.5MB) 0.0% used To Space: capacity = 11010048 (10.5MB) used = 0 (0.0MB) free = 11010048 (10.5MB) 0.0% used PS Old Generation // 老年代内存使用情况,大约使用了2709MB,使用率近100%(导致OutOfMemoryError) capacity = 2841116672 (2709.5MB) used = 2840991320 (2709.38045501709MB) free = 125352 (0.11954498291015625MB) 99.99558793198338% used 4955 interned Strings occupying 422328 bytes.