1、栈区(stack)
由编译器自动分配释放,存放函数的参数值,局部变量的值等。
2、堆区(heap)
是一个可动态申请的内存空间(其记录空闲内存空间的链表由操作系统维护),在java中,所由使用new xxx()构造出来的对象都在堆中存储一般由程序员分配释放。
3、常量池
存放字符串常量和基本类型常量(public static final)
常量池的好处是为了避免频繁的创建和销毁对象而影响系统性能,其实实现了对象的共享。
4、变量
诸如int a = 3; long b = 255L;(L必须加,不加默认是int类型)的形式来定义,称为自动变量即变量。
值得注意的是,这里的a是一个指向int类型的引用,指向3这个字面值。这些字面值的数据,由于大小可知,生存周期可知(这些字面值固定定义在某个程序块里,程序块退出后,字段值就消失了),出于追求速度的原因,就存在于栈中。
另外,栈有一个很重要的特殊性,就是存在栈中的数据可以共享。
假设我们同时定义:
int a = 3;
int b =3;
编译器首先会处理 int a = 3,首先它会在栈中创建一个变量为a的引用,然后查找有没有字面值为3的地址,没找到,就开辟一个存放3这个字面值的地址,然后将a指向3的地址。接着处理 int b = 3;在创建完b这个引用变量后,由于在堆中已经有3这个字面值,便将b直接指向3的地址。这样,就出现了a与b同时均指向3的情况
【上文提到了“引用+数值+内存地址”这个三个名字,其中变量名就是引用,给变量赋的值就是数值,而所提到的内存是抽象的内容,让引用指向的不是数值,而是存存数值的那块内存地址】
定义完a与b的值后,再令a = 4;那么,b不会等于4,还是等于3。在编译器内部,遇到值4时,它就会重新搜索堆中是否有4的字面值,如果没有,重新开辟地址存放4的值;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b的值。
【定义变量,给变量赋值,然后在编译的过程中就可以将其保存在内存中了。】
经过官方文档考察,各方求证,int a = 3存储到栈还是堆中?其实变量a 和值3都存储在栈中,JVM内存模型如下:
更具体的来说是存储到虚拟机栈,将数值3存储到操作数栈,将变量a存储到局部变量表栈。
@精彩好文章推荐人——康宁
人生在于勤,志达天下