我们平时在运行java程序时会在内存中划分出5个空间进行数据的存储:堆,栈,方法区,本地方法区,寄存器。
在这里我们主要简单的阐述一下堆和栈,其余的如果有空的话会进行讲解。
ok,现在我们需要知道一下什么是堆,什么是栈?
简单的来说,网上有很多对堆栈的理解。很多都是千篇一律的解释,在这里不详细做讲解。
对我而言,堆栈就是为了存放“数据”而产生的空间。
1.栈:用来存放 基本数据类型,局部变量,用完就消失(先进后出)
2.堆:存放通过new关键字创建的实例化对象以及数组
3.堆空间远远大于栈
记住这3点,我们先举几个例子来强化认知
demo1:
main()
int x = 1;
other()
int y = 1;
主函数中定义一个int类型的变量x,赋值为1.在other方法(包含其他方法)中定义一个变量y,赋值为1。
执行步骤:
1——先执行main方法(别问我为什么,程序的入口),JVM执行,紧接着在栈空间中开辟一个空间来存放变量x同时给它赋值。
2——JVM执行other方法之后,又在栈空间中开辟一个空间来存放变量y同时赋值。
这个时候栈空间里已经开辟了两个空间了,此时它们同时存在,并且不影响对方运行。
3——other方法执行完毕,y变量即刻释放,为它开辟的变量消失。但是main空间不会有任何变化,依旧会存在。待main方法执行完毕之后,main方法空间释放
demo2:
main()
int[] x = new int[1]
定义一个数组x,长度为1
执行步骤:
1——执行main方法,在栈中开辟一个空间存放变量x,同时在堆中开辟一个空间存放new int[1],接着会把new int[1]引用这个数组
2——将堆内存中的1赋值给[0]这个数组元素。之后变为{1}
demo3
main()
int[] x = new int[1];
x[0]=20;
x=null;
执行步骤:
1、2步骤和demo2相同
3——由于x被设置为了null,从而数组将不会再指向x。此时数组将被视为垃圾,jvm会启动垃圾回收机制,会将堆空间进行释放
demo4
main()
int[] x = new int[1];
int[] y = x;
y[0]=20;
x=null;
执行步骤:
1、与之前的操作一致
2——x指向y,并且由于x是指向数组的,所以y也是指向数组
3——将y指向[0]=20
4——由于x设为null,所以x不是指向数组。但是由于y现在是指向数组的,所以数组开辟的空间不被释放.由于x被设置成了null,所以x之前所开辟的空间也会被释放(但是不会通过GC处理)
栈和堆的特点
栈:
函数中定义的基本类型变量,对象的引用变量都在函数的栈内存中分配。
栈内存特点,数数据一执行完毕,变量会立即释放,节约内存空间。
栈内存中的数据,没有默认初始化值,需要手动设置。
堆:
堆内存用来存放new创建的对象和数组。
堆内存中所有的实体都有内存地址值。
堆内存中的实体是用来封装数据的,这些数据都有默认初始化值。
堆内存中的实体不再被指向时,JVM启动垃圾回收机制,自动清除,这也是JAVA优于C++的表现之一(C++中需要程序员手动清除)。