Java記憶體管理的進一步理解-類比過程圖解,java記憶體管理

來源:互聯網
上載者:User

Java記憶體管理的進一步理解-類比過程圖解,java記憶體管理
Java記憶體管理的進一步理解-類比過程圖解--轉載

 

java的記憶體管理分為:

1、堆記憶體;2、棧記憶體;3、方法區;4、本地方法區

/* 1:方法區       方法區存放裝載的類資料資訊包括:       (1):基本資料:       1)每個類的全限定名        2)每個類的直接超類的全限定名(可約束類型轉換)       3)該類是類還是介面       4)該類型的存取修飾詞       5)直接超介面的全限定名的有序列表       (2):每個已裝載類的詳細資料:       1)運行時常量池:       存放該類型所用的一切常量(直接常量和對其它類型、欄位、方法的符號引用),它們以數組形式通過索引被訪問,是外部調用與類聯絡及類型對象化的橋樑。它是類檔案(位元組碼)常量池的運行時表示。(還有一種靜態常量池,在位元組碼檔案中)。       2)欄位資訊:       類中聲明的每一個欄位的資訊(名,類型,修飾符)。       3)方法資訊:       類中聲明的每一個方法的資訊(名,傳回型別,參數類型,修飾符,方法的位元組碼和異常表)。       4)靜態變數       5)到類 classloader 的引用:即到該類的類裝載器的引用。       6)到類 class 的引用:       虛擬機器為每一個被裝載的類型建立一個 class 執行個體, 用來代表這個被裝載的類。  2:棧記憶體       Java棧記憶體以幀的形式存放本地方法的調用狀態(包括方法調用的參數,局部變數,中間結果等)。每調用一個方法就將對應該方法的方法幀壓入 Java 棧,成為當前方法幀。當調用結束(返回)時,就彈出該幀。        編譯器將原始碼編譯成位元組碼(.class)時, 就已經將各種類型的方法的局部變數, 運算元棧大小確定並放在位元組碼中,隨著類一併裝載入方法區。當調用方法時,通過存取方法區中的類的資訊,得到局部變數以及運算元棧的大小。       也就是說: 在方法中定義的一些基本類型的變數和對象的引用變數都在方法的棧記憶體中分配。 當在一段代碼塊定義一個變數時,Java 就在棧中為這個變數分配記憶體空間,當超過變數的範圍後,Java 會自動釋放掉為該變數所分配的記憶體空間, 該記憶體空間可以立即被另作它用。   棧記憶體的構成:       Java 棧記憶體由局部變數區、運算元棧、幀資料區組成。       (1):局部變數區為一個以字為單位的數組,每個數組元素對應一個局部變數的值。調用方法時,將方法的局部變數組成一個數組,通過索引來訪問。若為非靜態方法,則加入一個隱含的引用參數 this,該參數指向調用這個方法的對象。而靜態方法則沒有this參數。因此,在靜態方法裡無法訪問對象資訊。       (2):運算元棧也是一個數組,但是通過棧操作來訪問。所謂運算元是那些被指令操  作的資料。當需要對參數操作時如 a=b+c,就將即將被操作的參數壓棧,如將 b 和 c 壓棧,  然後由操作指令將它們彈出,並執行操作。虛擬機器將運算元棧作為工作區。       (3):幀資料區處理常量池解析,異常處理等  3:堆記憶體       堆記憶體用來存放由 new 建立的對象和數組。在堆中分配的記憶體,由 Java 虛擬機器的自動記憶體回收行程來管理。       在堆中產生了一個數組或對象後,還可以在棧中定義一個特殊的變數, 讓棧中這個變數的取值等於數組或對象在堆記憶體中的首地址,棧中的這個變數就成了數組或對象的引用變數。 
    引用變數就相當於是為數組或對象起的一個名稱, 以後就可以在程式中使用棧中的引用變數來訪問堆中的數組或對象。 
4:本地方法棧記憶體       與調用的本地方法的語言相關,如:調用的是一個c語言方法則為一個c棧。本地方法可以回調java方法。若有java方法調用本地方法,虛擬機器就運行這個本地方法。       在虛擬機器看來運行這個本地方法就是執行這個java方法,如果本地方法拋出異常,虛擬機器就認為是這個java方法拋出異常。       Java通過Java本地介面JNI(Java Native Interface)來調用其它語言編寫的程式,在Java裡面用native修飾符來描述一個方法是本地方法。 */

 

 

下面通過一個簡單的程式碼範例,理解Java中,記憶體是怎麼進行分配與管理的。樣本如下:

 

public class JavaRamExplain {      public static void main(String[] args) {          Person.whatCountry();                    Person sam = new Person("sam", 20);          sam.introduceSelf();      }  }  class Person {        private String name;      private int age;      public static String country = "china";        public Person(String name, int age) {          this.name = name;          this.age = age;      }        public void introduceSelf() {          System.out.println("My name's " + name + ",i'm " + age + " years old.");      }        public static void whatCountry() {          System.out.println("This people come from " + country);      }  } 

 

 

 

當開始運行JavaRamExplain類時,JVM便會開始進行記憶體的分配管理工作。

圖解過程為:

(圖片較大,看不清可以圖片右鍵-查看映像,進行查看原圖)

可以看到到第八步工作結束後:

棧記憶體中的資料全部被釋放(所以說棧記憶體中的資料的生命週期是已知並固定的,因為隨著方法的執行結束,棧記憶體便會進行釋放);

堆記憶體中的Person對象,現已沒有任何對象引用指向它,所以它將被視作記憶體中的“垃圾”,等待回收。(堆記憶體中的資料由java的記憶體回收機制自動進行處理,所以其生命週期不確定)

由圖中也可以看到:

類的方法會進行壓棧和彈棧,對應的,方法中用到的參數(變數)便會相應的在棧記憶體中進行儲存和釋放。所以棧記憶體用於存放局部變數(包括基本類型和參考型別)。

類的對象會被存放到堆記憶體中,相應的該對象所包含的成員變數也會被存放到該空間。

類本身將在jvm通過.class運行該類時就會被載入到記憶體中的方法區內,顧名思義,方法區用於儲存類的方法代碼,其中普通方法被存放在非靜態區,靜態成員(方法和變數)被存放在方法區中專門的靜態區當中。

棧記憶體是方法的運列區域(因為方法中定義的局部變數需要在棧裡開闢空間),方法區是方法的存放地區。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.