您的位置:首页 > 编程语言 > Java开发

JVM学习(1)-JVM内存模型

2017-08-28 11:10 330 查看
1. JVM(Hotspot)内存模型简介



如图所示,JVM的内存模型中主要涵盖了以下5个部分.

1.1 程序计数器

程序计数器主要存储每个线程执行的字节码指令的行号.线程私有.

Java方法中的代码经过javac处理后,在class文件中以Code属性表形式存在,表中以数值方式存储了相应的字节码指令.

当线程执行native方法时,存储的值为undefined.该区域不会出现OOM.

1.2 虚拟机栈

VM栈中以栈帧的形式存储了线程执行Java方法的信息.VM栈只有栈帧的入栈和出栈两种动作.线程私有.

1.3 本地方法栈

Native栈的作用和VM栈类似,当线程执行了非Java方法(如C实现)时,会在内存中开辟一份Native栈,用以存储改方法的执行信息.线程私有.

Hotspot中,VM栈和Native栈已经合二为一.

1.4 方法区

方法区用以储存常量,静态变量,类的符号引用等信息.为各个线程公有.

Hotspot中将垃圾回收分代的思想引申到了方法区,所以Hotspot中的方法区也就是持久带.

1.5 堆

堆内存的唯一作用就是存储对象实例.线程公有.

2. 代码演示内存溢出异常

2.1 堆溢出

public class JVMTest {
static class OOMTest {
};

public static void main(String[] args) {
/**
* 模拟堆溢出
*/
List<OOMTest> list = new ArrayList<OOMTest>();
while (true) {
list.add(new OOMTest());
}
}
}


对象创建过多导致堆内存不足.

2.2 方法区溢出

public class JVMTest {
static class OOMTest {
};

public static void main(String[] args) {
/**
* 模拟方法区溢出
*/
List<String> list = new ArrayList<String>();
int i=0;
while(true){
list.add(String.valueOf(i++).intern());
//String类的intern方法创建的字符串,不会在编译期而是在运行期放入方法区的常量池
}
}
}


常量池中字符串过多导致方法区内存不足.

2.3 VM栈溢出

public class JVMTest3 {
private int count = 1;

public void stackTest() {
count++;
stackTest();
}

public static void main(String[] args) throws Throwable {
JVMTest3 test = new JVMTest3();
try {
test.stackTest();
} catch (Throwable err) {
System.out.println("Stack length:" + test.count);
throw err;
}
}
}


方法调用层次过多导致栈深过大.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  jvm java 内存