JAVA-初步认识-第四章-内存空间的划分&栈内存&堆内存
一.
讲解完数组定义后,讨论一下它在内存中的分布问题。这是为了方便理解java在运行过程中,到底是怎么操作的。
只要java程序运行,就会在内存中开辟空间。
jvm空间就是内存为虚拟机划分出来的空间,jvm内部又划分了诸多小空间,每一个小空间的内部数据的处理方式都不同。从这里引出来两个问题,内存划分为几部分?每部分的数据处理方式是怎样的?
内存被划分为五块,这五块之间没有先后顺序。寄存器是留给cpu的,本地方法区目前涉及不到,它是和所在系统相关的,运行的是本地系统平台中的内容。方法区目前也不深究,我们今天主要讲解栈内存和堆内存的概念。
将看问题的角度拔高,从数组的角度提高到整个内存的划分。
二. 栈内存(栈是一个实际存在的东西,毕竟内存是一个实际的东西)
首先要明白,栈里面存的是什么?存储的都是局部变量,凡是定义在方法中的变量都是局部变量。局部变量在使用的时候,必须先有函数。先加载该函数,然后在所属区间定义变量。→int[] arry=new int[3] 这里arry作为局部变量是毋庸置疑的,同时也和数组挂钩。数组和局部变量挂钩时,数组是有用的,没有挂钩就变成了垃圾。
上面的截图显示出一个知识点,for语句中定义的变量也是局部变量,但是在for语句结束后,x就被内存释放了,到System输出语句执行时,内存中已经没有x变量了,DOS会直接报错。
变量有其作用域,一旦离开作用域,就会被自动释放。→栈内存处理数据的特点,速度比较快。局部变量的生命周期短,决定了栈内存的空间特性。
栈内存的更新速度比较快,变量的生命周期比较短。
这种情况比较少见,我们一般封装区的时候,都要起名字。(区应该是指代码区)
局部代码块在定义一个区间,在这个代码里的变量它的作用区间就这么大。局部代码块决定局部变量生命周期。小程序没什么用,大程序有用。
栈内存的特点,可以快速地释放存储在其内部的局部变量,这也和局部变量的作用域有一定联系,两者一个是顶层,一个是底层。
栈和堆对比,变量和数组对比。栈很快释放作用完的变量,堆是保存所有数据,要么全部保留,要么全部变为垃圾。
三. 堆内存
堆里面存放的是什么?存储的是数组和对象(其实数组就是对象),凡是new建立的都是在堆中,堆会随时释放么?(说的是,随时释放里面的数组)如果能随时释放,那和栈就没什么区别了。→(栈的内部是用变量名,来区分数据)堆的内部是划分一个个小格,里面存放的都是一个个变量,堆本来就是变量的容器。那么栈里面装的也是可以随时消失的变量么,这和之前讲述的程序执行过程中形成的栈概念不一样啊?不能随便消失,数组中的一个变量无用时,不能将整个数组消失,数组中的其他变量可能还要使用。
堆里面存放的是数组,数组是变量的集合,也就是说堆存放了很多变量的集合。
特点:
int[] arr=new int [3]; 变量arr在主函数中,是局部变量,在栈内存中。int [3]是数组对象,在堆里存放。堆里面存的都是实体,对象是实体,数组也是实体。什么叫实体,实实在在存在的个体。实体的作用就一个,封装数据,而且可以封装多个数据。堆里面放的是实体,实体里面装了n多数据,有一个数据挂了,其他数据都还能用,那么堆里面的数据就不能随便消失。而栈不是,有一个变量挂了,那就消失,它是独立存在的。
对数组中的变量进行赋值,和之前基本数据类型的变量赋值没什么区别。
上图主函数在执行的时候,主函数要进内存,要进栈里面。为什么要进栈里面?因为局部变量都在方法里,方法不进栈,局部变量就没法进栈。先是主函数main和局部变量arr(arr即是局部变量,也是数组名称)进入栈,接着要将右边int[3]赋值给左边,右边不是一个具体值,是一个实体,而实体创建在堆里面。首先通过new关键字,在堆内存里开辟一个空间,这个空间有一个特点,内存在存储数据的时候,都是通过地址来体现的(堆里面存放了多个数据)。所谓的内存地址,就是一串连续的二进制编码,但是数字位很长,就采用16进制来表示。因此,给实体分配一个内存地址。分配好地址,数组就得到了一个空间。数组这个实体在内存中产生后,它都会进行一次默认初始化,不同类型的数据,堆内存在对其进行初始化时,初始值都不一样(现有内存地址,再有默认初始化值)。arr[0]=89; 这是一个赋值语句,arr[0]就相当于一个变量。堆内存中的变量都有一个特点,默认初始化值。数组是个实体,里面要存储很多数据。给数组中的元素或变量赋值,没有什么太多的变化。
补充:int [] arr=new int[3]; 首先要强调一点的是,变量放在栈中,而数组或实体放在堆中。虽然左右两侧建立了赋值关系,但是两边在内存中的分布完全不一样(栈内存和堆内存对各自数据的处理方式也不一样)。→可以这么来分析左右两侧,数据是一样的,但是在左右两边存放数据的容器是不一样的,人是一样,在家住的房间和在学校住的房间不一样。
注解:对变量进行常量赋值和数组索引赋值,是完全不一样的,机制不同。名为arry的变量想要得到一个数据,常量赋值是直接将数据输送给栈内存中的局部变量arry,但是如果是将数组中的数据赋值给变量,那么我们传送的给arry的是数据的内存地址,由变量自己根据地址来数据中寻找数据。→局部变量获得数据的两种形式,被动获得的,主动追寻的。如果如果没有给定数组中数据的内存地址,那么就是空,null。这时数组实体没有被调用,就称为垃圾。由没有调用的数组垃圾由引申出来一个垃圾回收机制,特点在于回收的不定时性。
总结:本节讨论的是栈内存和堆内存对于数据的处理方式,以及两者之间进行数据赋值时的一些原理。