说起jvm就避免不了谈及jvm的内存划分。本文主要说一下hotspot运行时数据区域的的划分和常见的Out Of Memory演示demo。本文主旨在记录自己所学知识,同时方便后续查阅,有不足支出请大家指正。
一、hotspot的内存分区
hotspot的jvm运行时数据区域分为堆、栈、方法区(永久代)、程序计数器。
二、各分区的简要介绍
堆
堆又细分为新生代和老年代。新生代又细分为Eden空间、from survivor空间和to survivor空间,其中Eden:survivor=8:1(默认情况)。可以通过-Xms10m和-Xmx20m来设置堆内存的大小。可以通过-XX:NewSize=10m和-XX:MaxNewSize=20m来设置新生代的大小。可以通过-XX:NewRatio=2(老年代是新生代大小的2倍)来设置老年代和新生代的比例,通过-XX:SurvivorRatio=8来设置Eden和survivor的比例。
堆上会抛Out Of Memory异常的demo
//package OutOfMemory;//注释掉
import java.util.ArrayList;
public class JavaHeapSpace {
public static void main(String args[]){
ArrayList arryList=new ArrayList();
int i=0;
while(true){
i++;
arryList.add(String.valueOf(i));
if(i<0){
break;
}
}
}
}
其中包名我是注释掉的,因为我是在cmd进行编译和运行。若加上包名会报找不到主函数的异常,执行结果如下:
栈
栈又分成虚拟机栈和本地方法栈,可以通过-xss10m来设置线程栈的大小
栈异常之StackoverflowError
//package OutOfMemory;//注释掉
import java.util.ArrayList;
public class StackOverflow {
public static void stackoverFlow () {
stackoverFlow();
}
public static void main(String[] args) {
stackoverFlow();
} }
栈异常之 unable to create native thread
package OutOfMemory;
public class ThreadStack {
public void notStop(){
while(true){
}
}
public void threadStack(){
while(true) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
notStop();
}
});
t.start();
}
}
public static void main(String args[]){
ThreadStack threadStack=new ThreadStack();
threadStack.threadStack();
}
}
以上是常见的两种栈溢出异常。
方法区(永久代)
方法区(永久代)可以通过调整-XX:PermSize=10m和-XX:MaxPermSize=10m来设置方法区的大小,不过此区域有最小默认值。即想调整方法区比较小时,不一定生效。如下案例代码在jdk1.6下是可以出现异常的,在jdk1.7及以上不会出现异常
//package OutOfMemory;
import java.util.ArrayList;
public class PermGenSpace {
public static void main (String args[]){
ArrayList arryList=new ArrayList();
int i=0;
while(true){
arryList.add(String.valueOf(++i).intern());
}
}
}
最后一个是程序计数器,此区域是不会出现OutOfMemoryError的。