Java程序在运行时都要开辟空间,任何软件在运行时都要在内存中开辟空间,Java虚拟机运行时也是要开辟空间的。JVM运行时在内存中开辟一片内存区域,启动时在自己的内存区域中进行更细致的划分,因为虚拟机中每一片内存处理的方式都不同,所以要单独进行管理。
JVM内存的划分有五片:
-
寄存器;
-
本地方法区;
-
方法区;
-
栈内存;
-
堆内存。
栈内存: 栈内存:栈内存首先是一片内存区域,存储的都是局部变量,凡是定义在方法中的都是局部变量(方法外的是全局变量),for循环内部定义的也是局部变量,是先加载函数才能进行局部变量的定义,所以方法先进栈,然后再定义变量,变量有自己的作用域,一旦离开作用域,变量就会被释放。栈内存的更新速度很快,因为局部变量的生命周期都很短。(主要存储声明的变量)
堆内存::存储的是数组和对象(其实数组就是对象),凡是new建立的都是在堆中,堆中存放的都是实体(对象),实体用于封装数据,而且是封装多个(实体的多个属性),如果一个数据消失,这个实体也没有消失,还可以用,所以堆是不会随时释放的,但是栈不一样,栈里存放的都是单个变量,变量被释放了,那就没有了。堆里的实体虽然不会被释放,但是会被当成垃圾,Java有垃圾回收机制不定时的收取。(存储的变量的值,可能是对象也可能是单个值,数组等等;万物皆对象)
详解:以下图为例,栈中存的是变量,堆中存的是对象。对象会分配一个内存地址,然后在栈中,会被变量引用,所以所在这种情况下,访问变量获取对象其实就是通过内存地址访问的,获取对象后可以再通过访问索引获取值。
如果堆中有对象,但没被引用,那么就可以想到java的垃圾回收机制,没被引用的对象将不定时进行回收。
扩展
讲到堆和栈必须讲一讲HashCode()与Equals()。
这就得提到一个java容器Set,它的属性是无序,元素不可重复。想一想底层,元素不可重复,那么肯定就会通过equals方法进行比较,如果存入的值相同,那么会替换之前的值。 如果Set中已经有十万条数据了,然后你在添加一个数据,是不是应该比较十万次,效率低下。那么在这里通过把内存地址传给哈希函数然后生成hash值;获取hash值之后,通过它能快速找到一个区域,将所添加的值与这区域内的值进行比较,如果没有相同的值就会添加进去,如果有相同的值,那么这就产生了哈希冲突,也叫哈希碰撞。
解决哈希冲突的方法,这里介绍两种,一种是拉链法,就是如果该区域被占用了,那么通过指针指向下一个地址,把值存在2位置
方法二寻址法,如果1位置被占用了,然后看看1的后面有没有位置可以
详情参考:https://ithuangqing.blog.csdn.net/article/details/103344078