two targets
One:验证java虚拟机规范中描述的各个运行时区域存储的内容;
Two:在工作中遇到OOM时能根据异常的信息快速判断是哪个区域的内存溢出,知道怎样的代码会导致这些区域内存溢出,以及如何处理。
-java堆溢出
java heap用来存放对象实例,不断的创建对象,并保证这些对象可达。在达到最大容量限制就会产生内存溢出。-Xmx, -Xms, -Xmn(Young)。-XX:+HeapDumpOnOutOfMemoryError可以在溢出时dump出当前的内存堆存储快照。
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.662 secs]
内存泄露:无意义对象仍然存活,导致的异常。
内存溢出:对象确实都必要存活。
-JVM Stack&native method Stack OOM
如果线程请求的栈深度大于虚拟机允许的最大深度,StackOverflowError。
如果虚拟机在扩展栈时无法申请到足够的内存,OutOfMemoryError。
public class JavaVMStackSOF{ private int stackLength = 1; private void stackLeak(){ stackLength++; stackLeak(); } public stack void main(String[] args){ 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
操作系统分配给每个进程的内存是有限制的,JVM提供了参数控制java堆(Xmx)和方法区(MaxPermSize)的内存大小,剩下的内存就由虚拟机栈(JVM Stack)和本地方法栈(Native Method Stack)瓜分。
public class JavaVMStackOOM { private void dontstop() { while (true){} } public void stackLeakByThread(){ while (true){ Thread thread = new Thread(new Runnable(){ @Override public void run(){ dontstop(); } }); thread.start(); } } public static void main(String[] args) { JavaVMStackOOM oom= new JavaVMStackOOM (); oom.stackLeakByThread(); } }
运行结果:
Exception in thred “main” java.lang.OutOFMemoryError: unable to create new native thread
-Method Area & Runtime Constant Pool
运行时常量池是方法区的一部分