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

来源:互联网 发布:手机淘宝直播怎么开通 编辑:程序博客网 时间:2024/05/17 03:05

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;        }    }}

方法调用层次过多导致栈深过大.

原创粉丝点击