时间很快,悄然间就来到了11月,不知不觉开学已经两个月了。算算看再有半年就毕业了,大学的美好生活即将离我远去,马上就要进入社会,有些许迷茫,有些许畏惧,有些许不舍又有些许期待,呵呵,难道这就是所谓的毕业综合症。
好了,言归正传,前几天在学习java在内存中是如何运行的,发现不少java初学者对此都不是很清楚,包括一些编程还可以的同学,偏偏不论是在面试,还是要考SCJP,java内存分析还是很重要的。在此,同样以一个初学者的身份分享一下我的思路,与大家共同探讨。
首先,无论你写一段什么样的代码,代码都是存储在硬盘中,使用时才通过内存调用。
其次,存放数据的内存大致分为4块,分别是code代码块,static静态区,stack栈,heap堆。(其实还有文字常量区,这次暂不讨论)。在java我们写完一段代码,调用时代码时java虚拟机会把代码编译成.class文件,.class文件会存放在程序代码区也就是我所说的代码块。而后计算机开始从main一行行解读程序,main方法放在static静态区,这也就是为什么main方法要用static修饰的原因。
现在我们开始重点分析程序在堆栈里的存放,以两段简单代码为例。
1、
2、
3、
4、
5、
6、
7、
8、
9、
10、
11、
12、
13、
14、
15、
16、
17、
18、
19、
20、
21、}
输出结果:
23
12345
com.scjp.memory.Student@1c78e57
真正算起来有效代码不到20行,我们结合图片对其进行内存分析。首先计算机从第3行main方法开始读起,读到第4行Student p=new Student(23,12345);时,系统在栈空间创建了个对象P,p指向堆空间里new出来的一个新的Student对象,该对象此时在堆空间中的有属性age,number,方法test(){},还有this,此时该对象的初始值为age=0,prower=0。p其实就是该对象的内存逻辑地址,映射其内存物理地址(相当于c的指针)。
紧接着程序读到第4行小括号中内容时,程序跳转到第13行,程序将数值23,12345传入Student中,public Student(int age,int number)中age与number俱为形参,注意:此时栈空间中age=23,number=12345,堆空间的age,number还是为0。通过第14,15行的this,(p指向this,this指向对象本身)将age与number的值传入堆空间中,此时堆空间的对象age=23,number=12345,而栈空间中的age与number被内存清除,这就是所谓的java中的垃圾回收机制,自动回收指针,释放内存,避免了c语言中指针忘记清空造成的内存溢出。通过这里也可以看出第11,12行的age,number为全局变量而13行中的age,number为局部变量,局部变量作用域至第16行的大括号而结束。好了,程序继续运行至16行后转回第5行,对象p调用test方法,程序转到17行,输出age与number的值。紧接着程序转回第6行输出p,从运行结果可以看出输出的值就是一段内存地址。所以说p就是对象的内存逻辑地址。
现在我们把代码改一下,将第14,15行中的this.去掉改成age=age,number=number。此时输出的最终结果是什么?答案显而易见,数值传入栈中的age,number后,因为没有this,值没有传入堆空间内,16行后栈空间的age,number被内存清除,而堆空间的age,number还是为0。所以打印出来的值为0。
这就是最简单的java内存分析,以后我还会逐步分析更复杂的java程序,希望能对大家有所帮助。