一、内存溢出
虚拟机栈和本地方法栈溢出:-Xss256k
package com.jedis; import java.util.LinkedList; import java.util.List; public class Demo1 { private int len = 1; private void fun() { len++; fun(); } public static void main(String[] args) { Demo1 t = new Demo1(); try { t.fun(); } catch (Throwable e) { System.out.println("Length = " + t.len); e.printStackTrace(); } } } /* Length = 3257 java.lang.StackOverflowError */
Java堆溢出:-Xms5M -Xmx5M -XX:+PrintGCDetails -verbose:gc
package com.jedis; import java.util.LinkedList; import java.util.List; public class Demo1 { public static void main(String[] args) { List<Object> list = new LinkedList<>(); int i = 0; while(true) { i++; if(i%10000==0) System.out.println("i = " + i); list.add(new Object()); } //String[] strings = new String[1000000000]; } }
方法区和运行时常量池溢出:-XX:MaxMetaspaceSize=3M
package com.jedis; import java.util.LinkedList; import java.util.List; public class Demo1 { public static void main(String[] args) { List<Object> list = new LinkedList<>(); } } /* Error occurred during initialization of VM OutOfMemoryError: Metaspace */
本地直接内存溢出:-Xmx10M -XX:MaxDirectMemorySize=10M
package com.jedis; import java.lang.reflect.Field; public class Demo1 { public static void main(String[] args) { Field unsafeField = Unsafe.class.getDeclaredField()[0]; unsafeField.setAccessible(true); Unsafe unsafeInstance = (Unsafe)unsafeField.get(null); while(true) { unsafeInstance.allocateMemory(1024*1024); } } } /* */
二、垃圾收集器与内存分配策略
GC要做的事:
1、Where/Which?
2、When?
3、How?
where:堆/方法区(元数据空间)
which:引用计数法/可达性分析法
引用计数缺点:相互引用
A +1
B +1
C 0
A-->B
B-->A
A、B组成孤岛,但是两个在计数上不为0
python-引用计数法
---
可达性分析:
GC Roots
1、虚拟机栈引用的对象
2、方法区类属性引用的对象
3、方法区常量引用的对象
----
怎么回收?
标记-清除算法(Mark-Sweep):直接把可回收的标记后清除——>不连续内存碎片——>无法放下大对象
复制算法(Copying):区域一分为二,存活对象一一复制过来,然后一股脑的把另一个全部释放——>内存拷贝耗时、任何时候都有一半空间空着
标记-整理算法(Mark-Compact):存活对象按照某种顺序排列——>标记、移动耗时
分代收集算法:90%对象朝生夕死——>堆分为新生代(刚new的对象)、老年代(活过多少次GC过程提取到老年代)——>定制不同的GC算法
G1:JDK1.8后常用了——>把新生代、老年代分的更小
Eden:to survival:from survival
8:1:1