在J2SE中,通過進行內存分析,可以讓我們更好的理解我們的程序在內存中是怎么被分配內存的。也能讓我們更好的理解我們的代碼是怎么運行的。
對于我自己來說分析內存也是一件很有趣的事情。所以下面通過一個例子來總結一下程序運行過程的中內存分配.
### 程序實例
~~~
public class Point {
double x,y,z;
Point(double _x,double _y,double _z)
{
x=_x;
y=_y;
z=_z;
}
void setX(double _x)
{
x=_x;
}
double getDistance(Point p)
{return (x-p.x)*(x-p.x)+(y-p.y)*(y-p.y)+(z-p.z)*(z-p.z);}
}
~~~
~~~
public class TestPoint {
public static void main(String[] args) {
Point p=new Point(1.0,2.0,3.0);//第一步
Point p1=new Point(0.0,0.0,0.0);//第二步
System.out.println(p.getDistance(p1));//第三步
p.setX(5.0);//第四步
System.out.println(p.getDistance(new Point(1.0,1.0,1.0)));//第五步
}
}
~~~
### 內存分析
**第一步**
首先定義了一個變量,所以在棧內存中會分配一塊空間來存儲變量,變量名為P,它指向了一個new出來的對象,這個new出來的對象,當然是放到堆內存。
在執行的過程中調用了Point的構造方法.在執行構造方法的過程中,在棧內存中臨時分配了三個空間分別存儲_x,_y,_z,然后再把這三個值賦值給點對象中的x,y,z.

賦值完成后這些臨時分配的變量將會被取消.所以第一步執行完后的內存分配如下圖

**第二步**
第二步的執行過程和第一步類似,不再做贅述,該步執行完后的內存分配如下圖.

**第三步**
該步調用了一個方法,從方法中我們可以看到有一個形參.所以首先在棧內存中臨時分配一塊空間,保存這個形參,也就是局部變量P.再看getDistance()方法中我們實際傳入的是P1,所以將p引用P1引用的對象(這里注意區分此刻分配的局部變量P和第一步new出來的P不是一回事)
該步的方法是有返回值的,所以需要在棧中分配空間來保存這個返回值.內存分配圖如下

將返回值打印后,臨時分配的內存空間取消.其內存分配圖和第二步執行完后的內存分配圖是相同的.
**第四步**
從調用的方法上看,首先要在棧中分配一個臨時變量_x,值為5.0.然后再將值賦值給P指向的對象.執行完后臨時變量被取消.內存分配圖如下.

**第五步**
此表達式比較復雜,當一個表達式復雜的時候,我們要從里向外分析.
基于此原則,分析得到,首先要在堆內存中new一個對象,這時這個對象并沒有被引用
然后執行方法.上面我們已經分析過了,執行這個方法我們需要先在棧中臨時分配一個變量P,此時需要將new出的對象給臨時變量P,也就是說這個P引用我們剛剛new出的那個對象。
然后計算兩點的距離,這時需要一個臨時變量來保存返回來的數據.
方法執行完后,所有臨時分配的內存被取消.這時要注意的是我們new出來的對象是通過垃圾回收機制取消的。
內存分析如下圖

### 程序執行完后的內存分配
最后展示一張程序執行完后的內存分配圖

### 總結
對于內存分析之前認為挺難的,但是經過仔細分析后發現其實內存分析很簡單,只要大家能夠看明白以下這幾點,我想對于一些簡單的內存分析你一定沒有問題了.
(1)形參要臨時分配空間,程序執行完后要 取消空間分配.
(2)對于復雜的程序要從里到外分析.一步步來.
(3)有返回值的方法,其返回值也是要分配給一個臨時變量的.同樣的使用完后要取消.
(4)臨時new出來的對象是利用垃圾回收機制取消的.
(5)靜態成員變量時放在哪里的,是怎么分配內存的.(這個例子并沒有展示靜態成員變量的分配)