1,Java堆溢出
只要不断地创建对象,并且保证GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象,就会在对象数量到达最大堆的容量限制后产生内存溢出异常
解决
public class HeapOOM { static class OOMObject { } public static void main(String[] args) { List<OOMObject> list = new ArrayList<OOMObject>(); while (true) { list.add(new OOMObject()); } } }
java.lang.OutOfMemoryError: Java heap space Dumping heap to java_pid3404.hprof ... Heap dump file created [22045981 bytes in 0.663 secs]
a,内存泄露
通过工具查看泄露对象到GC Roots的引用链。,垃圾收集器无法自动回收对象了
b,内存溢出
检查虚拟机堆参数,是否可以调大
2,虚拟机栈和本地方法栈溢出
HotSpot虚拟机中不区分虚拟机栈和本地方法栈
public class JavaVMStackSOF { private int stackLength = 1; public void stackLeak() { stackLength++; stackLeak(); } public static void main(String[] args) throws Throwable { JavaVMStackSOF oom = new JavaVMStackSOF(); try { oom.stackLeak(); } catch (Throwable e) { System.out.println("stack length:" + oom.stackLength); throw e; } } }
stack length:2402 Exception in thread "main" java.lang.StackOverflowError at org.fenixsoft.oom.VMStackSOF.leak(VMStackSOF.java:20) at org.fenixsoft.oom.VMStackSOF.leak(VMStackSOF.java:21) at org.fenixsoft.oom.VMStackSOF.leak(VMStackSOF.java:21)
a,如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常
b,如果虚拟机在扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常
3,运行是常量池溢出
向运行时常量池中不断添加内容
public class RuntimeConstantPoolOOM { public static void main(String[] args) { // 使用List保持着常量池引用,避免Full GC回收常量池行为 List<String> list = new ArrayList<String>(); // 10MB的PermSize在integer范围内足够产生OOM了 int i = 0; while (true) { list.add(String.valueOf(i++).intern()); } } }
Exception in thread "main" java.lang.OutOfMemoryError: PermGen space at java.lang.String.intern(Native Method) at org.fenixsoft.oom.RuntimeConstantPoolOOM.main(RuntimeConstantPoolOOM.java:18)
4,方法区溢出
方法区用于存放Class的相关信息,如类名,访问修饰符,常量池,字段描述,方法描述等。
思路:运行时产生大量的类去填满方法区,直到溢出
public class JavaMethodAreaOOM { public static void main(String[] args) { while (true) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(OOMObject.class); enhancer.setUseCache(false); enhancer.setCallback(new MethodInterceptor() { public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { return proxy.invokeSuper(obj, args); } }); enhancer.create(); } } static class OOMObject { } }
Caused by: java.lang.OutOfMemoryError: PermGen space at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632) at java.lang.ClassLoader.defineClass(ClassLoader.java:616)