菜鸟学Java(二十三)——Java内存分析
我们常说的Java内存主要分为四大块(寄存器不在考虑之内,我们无法用代码来操控它):stack(栈)、heap(堆)、data segment(数据区)、code segment(代码区)。它们的主要用途如下图所示:
而在上面四个当中,我们经常谈论的是右边那两个家伙——stack和heap。今天我们就来聊聊Java代码在运行的过程中,在stack和heap中到底是什么样子的吧。
我们先看下面一段代码:
public static void main(String[] args) { TestReference testReference = new TestReference(); int age = 1; Person xiaoqiang = new Person("小强", 21); Person xiaoming = new Person("小明", 22); testReference.selfPlus(age); System.out.println("age经过selfPlus方法的处理后为:" + age); testReference.changeName(xiaoqiang); System.out.println("小强经过changeName方法的处理后的名字为:" + xiaoqiang.getName()); testReference.changeAge(xiaoming); System.out.println("小明经过changeAge方法的处理后的年龄为:" + xiaoming.getAge()); } public void selfPlus(int i) { i = i + 1; } public void changeName(Person person) { person = new Person("小刚"); } public void changeAge(Person person) { person.setAge(25); }
执行完以上代码,会打印出什么内容呢?如果你Java基础还可以,那么很容易就能知道会输出什么内容,想要知道以上代码会打印什么内容,需要你明白Java代码在stack和heap中是怎么工作的。下面我们结合几张图来看看:
int i = 1; Person xiaoqiang = new Person("小强", 21); Person xiaoming = new Person("小明", 22);
当我们执行完上面三行代码时,内存中的情况如下图所示:
我们知道stack是用来存放变量的,所以age、xiaoqiang和xiaoming三个变量会被存放到stack里,而age又是int类型,所以它的值也会被存放在stack里面。xiaoqiang和xiaoming为Person类型的引用变量,所以stack只会存放它们的一个引用,也就是对应对象的内存地址,而它们真正的内容被存放在了heap里面。
当执行到testReference.selfPlus(i);时,selfPlus(int i)方法被调用,此时会在stack中为形参I开辟一块内存空间,并将其值设置为1,此时内存中的情况如下:
因为调用selfPlus(int i)方法时,将age作为形参传递给该方法,相当于将age的值复制一份给i,所以现在i的值为1,接着执行i = i + 1;此时i的值被修改为2,如图:
此时被修改的只是age的副本,而并非age本身,所以age仍为1,当selfPlus(int i)方法被执行完,i被销毁,age不变。接下来看xiaoqiang,当调用changeName(Person person)方法时,会在stack中为person分配一块空间,里面存放的是xiaoqiang指向的地址,如图:
然后执行到person = new Person("小刚");时,由于又new了一个Person对象,所以在堆中会新建一个person,姓名叫小刚,并且会将person执行小刚的地址,如图:
此时,person指向的对象由小强变成了小刚,但是xiaoqiang所指向的对象仍然是小强,并没有发生任何变化。当changeName方法执行完以后,person被销毁,而小刚也会因为没有任何对象对其进行引用,随后被垃圾回收器回收掉。
下面到了最后一个方法了,当执行testReference.changeAge(xiaoming);时,调用changeAge(Person person)方法,同样会在stack中为person分配一块空间,这次里面存放的是xiaoming对应的内存地址,如图:
然后执行person.setAge(25);,此时person指向的对象为小明,所以在执行setAge方法时,修改的就是heap中小明的属性值,此时小明的年龄被修改为25,。方法执行完毕,person被销毁,内存中最终结果如下:
内存中的最终情况就如上图所示,当然当main方法执行完以后,之前创建的所有对象都会被销毁。OK,每天上班做项目的你是不是把一些基础的东西忘了呢?如果是的话就赶快来补一补吧,好处还是很多的。