JVM运行时数据区
- 程序计数器:存放线程执行位置(main函数也是一个线程);
- 虚拟机栈(栈内存):
- 生命周期和对应的线程相同,存放该线程的局部变量、对象的引用;
- 方法中可能嵌套调用别的方法,这些方法的变量以”先进后出、后进先出“的方式在栈内存中存储,所以内层方法无法访问外层方法的变量(他们在栈底),执行外层方法时内层方法的变量已经弹出栈消失了,所以外层方法也不会访问到内层方法的变量;
- 一个方法的执行过程,就是这个方法对于帧栈的入栈出栈过程;
- 本地方法栈:
- 作用和虚拟机栈完全相同;
- 虚拟机栈对应普通的java方法,本地方法栈对应native方法;
- native方法是一个java调用非java代码的接口;
- 方法区:
- JVM内存管理中最大一块;
- 存储常量(final修饰)、类变量/成员变量(static修饰)、类信息(每个类的访问控制符、修饰符、继承关系等);
- 堆内存:JVM启动时创建,存放对象本身,不存放对对象的引用(引用存在栈内存);
堆内存和栈内存的区别
- 变量存在栈内存中(无论是static类变量还是对象的变量),已经不在其作用域中的对象要及时弹出栈;
- new出来的对象或实例,它的名称存在栈内存中,实体存在堆内存中,名称通过实体在堆内存的地址引用实体;
- 垃圾回收的目标是堆内存中失去引用的对象实体;
- 栈内存一般是用物理一级缓存实现,堆内存一般是用物理二级缓存实现,栈内存存取速度快于堆内存,代码本身存储在磁盘中,和堆栈内存无关;
- 堆主要用来存放对象的,栈主要是用来执行程序的;
- 每个线程有自己的栈内存(栈内存是线程私有的),在一个JVM实例中(一个java应用对应一个JVM实例),堆内存只有一个(堆内存是线程共享的);
- 在java中:
- 基本数据类型(int, short, long, byte, float, double, boolean, char),他们存储在栈内存中,函数调用它们的时候是”传值”;
- 复杂数据类型(数组, 对象, map, List, Set等),他们的实体存储在堆内存中,栈内存中只存储他们的对象的名称、通过堆内存的地址引用实体对象,函数调用它们的时候是”传引用地址”;