java程序执行过程的内存解析,包括java在创建类时,在调用方
法时的内存解析。
java程序的入口是main函数,所以,看一个java程序可以撇开
其他的代码,直接找main函数,再根据逐条向下去看创建的类与
调用的方法,如下简单代码:
public class Test {
int i;
int j;
Test() {
}
Test(int x) {
this.i = x;
}
void mthod(int y) {
this.j = y;
System.out.println(this.j);
}
public static void main(String[] args) {
Test test = new Test();
Test test1 = new Tetst(5);
test.mthod(5);
test1.mthod(9);
}
}
以上代码是一个比较简单的对象创建与调用,下面分析内存过程
我们编写的源程序在内存中一般被存在四个区域
区域 | 存放内容 |
---|---|
code segment | 存放代码 |
data segment | 存放静态变量与常量 |
stack(栈) | 存放变量 |
heap(堆) | 存放new出来的东西 |
首先,在对象没有被创建与方法没有被调用的时候,内存区里任何内存不被占用,只有在创建语句被执行时才占用相应的内存区。创建变量时创建了一块stack的内存单元,而创建一个对象时,则创建了一个stack单元和一个heap单元。
对于这个程序来说,首先找程序入口main()函数,
public static void main(String[] args) {
Test test = new Test();
Test test1 = new Tetst(5);
test.mthod(5);
test1.mthod(9);
}
第一句,创建了一个名为test的Test类,调用了Test()无参构造方法则在内存中,其变量名为test,则在stack中,创建了一个名为test的内存单元,其内容为一个地址xxx,同时又在heap区里创建了一个大的内存区,在这个内存单元里同时为Test类中的变量i,j也分配了内存空间,并且初始值都为0,而stack中的test变量内容xxxx储存的是一个地址,该地址指向heap区内的类的空间。如下图:
第二句,同样创建了一个Test类,名为test1的对象,与test不同的是,创建test1调用的Test(int x)的带参数的构造方法,对于构造方法中的int x,则先在stack中创建一个名为test1的变量,变量内容指向heap内的一块区域;同时也分配了一个名为i的变量的内存空间,其值为5,如代码:
Test test1 = new Tetst(5);
同时在heap中,同样创建了一快内存区域,其中同样包含了成员变量i与j,此时内存如图:
如图,此时,把变量x的值传给heap相应的内存区的对应的变量i的值,此时,变量i的值变为5.
该语句执行结束后,变量x的内存空间成为垃圾,被垃圾回收,对象创建完毕。
当调用test1的mthod方法时,内存情况类似,当执行到以下代码时
test.mthod(5);
计算机会在stack内分配一个内存空间给方法的局部变量y,其值为5,并指向test对象在heap中的成员变量j,如下图
然后会把y的值传给成员变量j,方法执行完毕,则变量y的内存空间被释放。如下图
对于test1对象,同样是此过程。
当整个程序执行完毕以后,变量test与test1所在的stack内存单元会被释放,则其对相应的在heap内的内存单元的引用也消失。如图
而对于heap区的对象的内存区而言,如果对其的引用消失,则这块内存失去其价值,则会被当作是垃圾而被垃圾回收机制回收掉。
另外,还有关于继承中的一些内存解析情况,留在下次。