在JVM中我们可以了解到其将内存分为两种:栈内存 / 堆内存;
首先我们来说下[栈内存]和[堆内存]区别:
①栈内存:栈内存是用来存储在java函数中定义的一些基本类型的变量和对象的引用变量,这些变量的作用范围是有限的,一旦这些变量的范围超出作用域之后,就会自动在内存中释放这些变量所占用的内存空间,从而可以被重新使用;
②堆内存:堆内存用来存放由New创建的对象和数组,和栈内存的区别在于它的回收机制不是由自己掌控,而是由系统函数来实现的,在JVM内存吃紧的时候会调用系统的.GC()函数去完成堆内存中垃圾的清除;
下面我们通过简单的代码和图片案例来展现在JVM中[栈内存]和[堆内存]:
①我们在栈中存储数据的时候存储在栈中的数据是共享的;
public static void mian(String[] args){
int a=1;
int b=1; //在栈内存中,首先定义a并开辟空间赋值为1;在定义b的时候会直接将b指向数值<span style="color:#FF0000;">1</span>所在的空间;即在栈中的数据存储会是共享的;
b=3; //当我们在重新给b辅助的时候,首先会在栈的存储空间中找是否存在单独的数据<span style="color:#FF0000;">3</span>,如果存在则直接指向<span style="color:#FF0000;">3</span>所在的存储空间,否则重新开辟空间存储<span style="color:#FF0000;">3</span>这个数据;
}
②在①中我们提到的是一般变量,在栈内存中我们也会存储引用变量,而我们new出的数组变量会存储在堆内存中:
public static void main(String[] args) {
int[] m = new int[3]; //定义数组m
for (int i = 0; i < m.length; i++) {
System.out.println(m[i]); //输出m定义后的初始值
}
m[0] = 1;
m[1] = 2;
m[2] = 3; //对m元素重新赋值
for (int i = 0; i < m.length; i++) {
System.out.println(m[i]); //输出重新赋值后的元素值
}
int[] n = new int[2]; //定义数组n
n[0] = 1;
n[1] = 2; //对n元素重新赋值
for (int i = 0; i < n.length; i++) {
System.out.println(n[i]); //输出重新赋值后的元素值
}
}
在上面的代码中我们定义出数组m和n,在我们没有对数组进行赋值时在堆内存中的数组元素值也是存在的,我们通过输出语句(第一个for循环)展现了初始化之后数组的初始值,在这里的integer类型的数据初始值为0;在对数组元素重新赋值时修改堆中元素值;
在左边的图中我们可以明确看出数据中的引用变量和数组变量在JVM内存中的分属情况;
③在之前我们有说道在栈内存中我们的数据是共享的,在堆内存中也存在数据公用的情况;如下:
public static void main(String[] args){
int [] a=new int[4]; //定义数组a
int [] b=a; //定义数组b,并对引用变量b赋值为a;
a[0]=1;
a[1]=2; //对a数组赋值
a[2]=3;
a[3]=4;
System.out.println(b[0]); //输出b数组的元素值
b[1]=5;
System.out.println(a[1]);
}
在上述代码中我们首先定义了数组a,此时将会在栈内存中开辟空间存储引用变量a,同时在栈内存中开辟空间存储new出来的数组初始值都为0;定义数组b,并将引用变量b的值赋值为a,即将b指向a在堆空间中new出的数组起始位置(类似于c中的应用&);当我们对数组元素重新赋值的时候将会同时影响到两个数组的元素值;
因此在堆和栈内存中虽然都存在共享的问题,但是它们的共享机制是不同的;这里是以一般变量和数组为例自己的个人理解,还请大牛多多指点,欢迎访问个人博客(http://cuiyongzhi.com)!