J2SE快速進階——Java記憶體分析,j2se進階java

來源:互聯網
上載者:User

J2SE快速進階——Java記憶體分析,j2se進階java

   

        程式的執行過程

        要在Java中分析記憶體,我們先來瞭解一下程式的執行過程:

        

         正如所示,大致分為3個步驟:

         1、最開始,我們的程式是存在於硬碟中的,當啟動運行時,程式會被載入(load)到記憶體中去,這裡的記憶體可以看做我們的記憶體條;

         2、此時,記憶體中除了存在剛載入的程式的代碼,還存在作業系統本身的代碼(好吧,此句可以當做廢話→_→),作業系統會找到程式中的Main方法開始執行程式;

         3、第三步就是本文的重點,系統在程式執行過程中對記憶體的管理。在Java中,記憶體大致會被分為四塊——heap(棧)、stack(堆)、data segment(資料區段)、code segment(程式碼片段),分別用來存放程式中的局部變數、new出來的對象或數組等、靜態變數、程式碼。

         這裡主要討論heap(棧)和stack(堆)。

          

          Java的資料類型

         先來複習一下Java的資料類型,Java中資料類型分為兩種,基礎資料型別 (Elementary Data Type)和引用資料類型,如:

         

        基礎資料型別 (Elementary Data Type)就這八種,引用資料類型包括類、數組、介面等。

      (初學者可能會把String、Integer等類型和char、int等基礎資料型別 (Elementary Data Type)混淆,這裡說明一下,Integer相當於int的“封裝類”,String可以看做是char[]類型的數組,此外,Byte、Float等類似。所以這些類型應噹噹做參考型別去對待。)

          

        記憶體分析

       正如第一張圖所示,程式運行時,我們定義的局部變數一般都存放於棧記憶體中,這些局部變數既可以是基礎資料型別 (Elementary Data Type)的變數(基礎資料型別 (Elementary Data Type)的變數在棧中直接儲存它的值),也可以是參考型別的變數(參考型別的變數在棧中儲存的是它所指向的堆記憶體中對象的地址)。

       堆記憶體中存放的就是參考型別變數的地址所指向的對象。        


       實踐出真知,下面具體在代碼中分析一下,希望您能抽出10秒鐘來仔細看一下這段代碼再繼續:      

public class MemoryAnalysis {public static void main(String[] args) {        Person person=new Person("小明",15);String newName="小紅";int newAge=18;person.SetName(newName);person.SetAge(newAge);person.SayHello();}}public class Person {public String name;public int age;public Person(String name,int age){this.name =name;this.age=age;}public void SetName(String name){this.name=name;}public void SetAge(int age){this.age=age;}public void SayHello(){System.out.println("我的名字叫"+name+",我"+age+"歲了");}}


       下面對Main方法中的代碼逐句分析  :

Person person=new Person("小明",15);

       執行個體化了Person類後:

       堆記憶體:堆記憶體中分配一塊記憶體用來存放Person執行個體person中的資料,因為person的name屬性為String類型,所以在堆記憶體中會另外分配一塊記憶體用來存放String類型的“小明”,person中的name中存放的只是一個地址(地址3),這個地址指向存放“小明”的記憶體塊;person中age屬性為int類型,所以直接在age的記憶體單元存放int類型的“15”。

        棧記憶體:因為person為參考型別,所以在棧記憶體中分配的記憶體單元person中存放的是一個指向堆記憶體中person執行個體的地址(地址1)。如果上面的代碼中只是定義了person,而沒有new,那麼只會在棧記憶體中分配一個person的記憶體單元,內才能中的值為空白。

      

        

String newName="小紅";
         

       因為newName類型為String類型,所以newName的實際內容也會存放於堆記憶體中,棧記憶體配置的記憶體單元newName中只是存放指向堆記憶體中“小紅”的地址。


int newAge=18;

          

      newAge的類型為int類型,所以直接將值(18)存放在棧記憶體配置的單元newAge中。

  

person.SetName(newName);

       到了函數這塊,會有一點點複雜,因為SetName(String name)函數有一個類型為參考型別參數name,而且傳入的實參為newName,這時newName中儲存的值(地址2)會賦值給這個name,所以這時newName和name儲存的地址相同(即同時指向“小紅”)。同理,當執行了SetName(String name)函數中的this.name=name時,會把棧記憶體中name中儲存的值(地址2)賦值給堆記憶體中person的name,此時person中的name裡儲存的也是指向“小紅”的地址。

       

       


        之後,person原來的name值“小明”會在某個時刻被java的記憶體回收機制所回收。

       

        方法執行完畢後,棧記憶體中變數name所佔的記憶體被回收。

       


person.SetAge(newAge);

          跟SetName(String name)一樣,執行時也會在棧記憶體中為形參age分配記憶體單元,只不過SetAge(int age)函數中的形參age為int類型,所以直接在棧記憶體配置的單元中直接儲存實參的值(18)即可。

        

           方法執行完畢後,棧記憶體中變數age所佔的記憶體被回收。

        

       

         以上就是這幾句代碼的執行過程。多少懂一些java基礎的您肯定已經猜出運行結果了:

         運行結果:            

          

       





聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.