内存溢出的种类
如果JVM里运行的程序, 它的内存堆和持久存储区域的都满了,这个时候程序还想创建对象实例的话,垃圾收集器就会启动,试图释放足够的内存来创建这个对象。这个时候如果垃圾收集器 没有能力释放出足够的内存,它就会抛出OutOfMemoryError内存溢出错误。
在抛出内存溢出错误的时候,一般都会提示内存泄露的种类,
1.堆(heap)内存泄漏
java.lang.OutOfMemoryError: Javaheap space:
大家都比较熟悉 ,通过设置-Xms2048m -Xmx4096m可以解决
2.栈(stack)内存泄漏:
stack over flow当前线程运行期间维护的中间变量等信息过多,
例如常见的死循环引起stack over flow
3.方法区(permanent heap)内存泄漏
java.lang.OutOfMemoryError: PermGen space:
发生的原因和类型装载、类型卸载有直接的关系,
通过设置-XX:MaxNewSize=256m -XX:MaxPermSize=256m可以解决。 一般情况下,当服务器内存过小,而提供了大量的访问服务时, 可能会缓存过多的数据对象造成堆内存溢出,当web应用不断扩大,
加载的lib库达到一定大小(4M)后,
就容易报PermGen OOM,也就是方法区溢出。
在Linux服务器中将参数写入环境变量:
export CATALINA_OPTS="-Xms2048m -Xmx4096m"
export JAVA_OPTS="-XX:MaxNewSize=256m -XX:MaxPermSize=256m"
Xmx 最大不要超过服务器物理内存的80%
1. 栈溢出实验
什么时候会让 Java 栈溢出啊?栈的基本特点就是 FILO(First In Last Out),如果 in 的太多而 out 的太少,就好 overflow 了。而 Java Method Stack 的功能就是保存每一次函数调用时的“现场”,即为入栈,函数返回就对应着出栈,所以函数调用的深度越大,栈就变得越大,足够大的时候就会溢出。所以模拟 Java Method Stack 溢出,只要不断递归调用某一函数就可以。
public class Test { private int stackLength = 0; public void stackOverflow() { ++stackLength; stackOverflow(); } public static void main(String[] args) throws Throwable { Test test = new Test(); try { test.stackOverflow(); } catch (Throwable e) { System.out.println("stack length: " + test.stackLength); throw e; } }}stack length: 1052Exception in thread "main" java.lang.StackOverflowError at com.sinosuperman.main.Test.stackOverflow(Test.java:8) at com.sinosuperman.main.Test.stackOverflow(Test.java:9) at com.sinosuperman.main.Test.stackOverflow(Test.java:9) at com.sinosuperman.main.Test.stackOverflow(Test.java:9) at com.sinosuperman.main.Test.stackOverflow(Test.java:9) ...
package com.sinosuperman.main;import java.util.ArrayList;import java.util.List;public class Test { private static class HeapOomObject { } public static void main(String[] args) { List<HeapOomObject> list = new ArrayList<HeapOomObject>(); while (true) { list.add(new HeapOomObject()); } }}[GC 17024K->14184K(49088K), 0.1645899 secs][GC 26215K->29421K(49088K), 0.0795283 secs][GC 35311K(49088K), 0.0095602 secs][Full GC 43400K->37709K(49088K), 0.1636702 secs][Full GC 49088K->45160K(49088K), 0.1609499 secs][GC 45312K(49088K), 0.0265257 secs][Full GC 49088K->49087K(49088K), 0.1656715 secs][Full GC 49087K->49087K(49088K), 0.1656147 secs][Full GC 49087K->49062K(49088K), 0.1976727 secs][GC 49063K(49088K), 0.0287960 secs][Full GC 49087K->49087K(49088K), 0.1901410 secs][Full GC 49087K->49087K(49088K), 0.1673056 secs][Full GC 49087K->316K(49088K), 0.0426515 secs]Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at com.sinosuperman.main.Test.main(Test.java:14)
package com.sinosuperman.main;import java.lang.reflect.Method;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;public class Test { static class MethodAreaOomObject { } public static void main(String[] args) { while(true){ Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(MethodAreaOomObject.class); enhancer.setUseCache(false); enhancer.setCallback(new MethodInterceptor() { public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { return proxy.invoke(obj, args); } }); enhancer.create(); } }}Exception in thread "main" net.sf.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:237) at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377) at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285) at com.sinosuperman.main.Test.main(Test.java:24)Caused by: java.lang.reflect.InvocationTargetException at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at net.sf.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:384) at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:219) ... 3 moreCaused by: java.lang.OutOfMemoryError: PermGen space at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631) at java.lang.ClassLoader.defineClass(ClassLoader.java:615) ... 8 more
package com.sinosuperman.main;import java.util.ArrayList;import java.util.List;public class Test { public static void main(String[] args) { List<String> list = new ArrayList<String>(); 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 com.sinosuperman.main.Test.main(Test.java:12)