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
运行时常量池是方法区的一部分