我见青山多妩媚,料青山见我应如是。
辛弃疾《贺新郎·甚矣吾衰矣》
JVM内存可分为三个区:方法区(method)、栈(stack)、堆(heap)。
一、方法区(method)
方法区又叫静态区,方法区中的数据被所有线程所共享,类信息、常量、静态变量都存储在方法区中。
二、堆栈(stack)
通常叫做栈,是线程私有的一块内存区域,JVM会自动管理栈。存放在栈中的数据大小以及生存期必须是确定的,而且存放于栈中的数据可以共享。栈用于存放基本变量的数据以及对象的引用。
2.1基本变量的存储
Java中,共有八种基本类型,即:int,short,long,byte,float,double,boolean,char(不包括String!)。这8种类型存放在栈中,存放时存放的不是变量名,而是“字面值”。比如,有如下定义:
int i = 0;
这里0便是一个字面值,而i是一个指向int类型的引用。由于字面值的大小可知(由于平台无关项,Java中基本类型的大小固定),生存期可知(字面值定义于某个程序块之中,程序块退出字面值消失),故为了追求速度,字面值存储于栈中。
另外,由于栈中的数据可以共享,对于以下语句:
int i = 1;
int j = 1;
编译器首先处理int i = 1;首先在栈中定义一个变量为i的引用,然后查找栈中有没有字面值为1的地址,没找到就在栈中开辟一个地址存放字面值1,然后将i指向该地址。接下来处理int j = 1;由于栈中已经有了1这个字面值,因此将j指向该地址便可。如下图所示:
2.2对象引用的存储
栈中还存放局部对象的引用,该引用并不是对象本身,而是对象在堆中的地址。若对象引用没有指向具体的对象,则对象引用是null。
另外,在Java中,数组是一种引用类型,所以数组引用也存储在栈中。
三、堆(heap)
堆是一块被所有线程共享的内存区域,堆可以动态地分配内存大小,生存期也不需要事先确定,JVM会自动管理堆。堆用于存放所有的对象实例(包括new出来的对象)。
由于数组是一种引用类型,所以数组元素也存储在堆中。