菜鳥學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,每天上班做項目的你是不是把一些基礎的東西忘了呢?如果是的話就趕快來補一補吧,好處還是很多的。




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM