java 堆(heap)、棧(stack)和方法區(method)

  • JAVA的JVM的內存可分爲3個區:堆(heap)、棧(stack)和方法區(method)

堆區:

  • 1.存儲的是new出來的對象和數組,每一個對象都包含一個與之對應的class的信息。(class的目的是獲得操做指令)
  • 2.jvm只有一個堆區(heap)被全部線程共享,堆中不存放基本類型和對象引用,只存放對象自己

棧區:

  • 1.每一個線程包含一個棧區,棧中保存的是全部的變量,包括基本類型和引用類型,棧中的每一個變量都包含類型、名稱、值這些內容,只不過基本類型變量的值爲一個具體的值,而引用類型的變量的值爲對象在堆中的地址。
  • 2.每一個棧中的數據(原始類型和對象引用)都是私有的,其餘棧不能訪問。
  • 3.棧分爲3個部分:基本類型變量區、執行環境上下文、操做指令區(存放操做指令)。

方法區:

  • 1.又叫靜態區,跟堆同樣,被全部的線程共享。方法區包含全部的class和static變量。
  • 2.方法區中包含的都是在整個程序中永遠惟一的元素,如class,static變量。
  • 3.字符串常量池就是存放在方法區。

堆和棧的不一樣:

  • <1>存數數據不一樣
  • <2>回收方式不一樣
    • 棧中當超過變量的做用域後,java會自動釋放掉爲該變量分配的內存空間,該內存空間能夠馬上被另做他用。數組和對象在沒有引用變量指向它的時候,才變成垃圾,不能再被使用,可是仍然佔着內存,在隨後的一個不肯定的時間被垃圾回收器釋放掉。
  • <3>速度不一樣

堆中分配的內存,由Java虛擬機的自動垃圾回收器來管理。

堆和棧的優缺點:

<1>堆的優點是能夠動態地分配內存大小,生存期也沒必要事先告訴編譯器,由於它是在運行時動態分配內存的,Java的垃圾收集器會自動收走這些再也不使用的數據。但缺點是,因爲要在運行時動態分配內存,存取速度較慢.
<2>棧的優點是,存取速度比堆要快,僅次於寄存器,棧數據能夠共享。但缺點是,存在棧中的數據大小與生存期必須是肯定的,缺少靈活性java

舉例: int a = 3; int b = 3;

編譯器先處理int a = 3;首先它會在棧中建立一個變量爲a的引用,而後查找棧中是否有3這個值,若是沒找到,就將3存放進來,而後將a指向3。接着處理int b = 3;在建立完b的引用變量後,由於在棧中已經有3這個值,便將b直接指向3。這樣,就出現了a與b同時均指向3的狀況。
這時,若是再令a=4;那麼編譯器會從新搜索棧中是否有4值,若是沒有,則將4存放進來,並令a指向4;若是已經有了,則直接將a指向這個地址。
所以a值的改變不會影響到b的值。數組

簡單代碼語句的執行過程:

系統收到了咱們發出的指令,啓動了一個Java虛擬機進程,這個進程首先從classpath中找到AppMain.class文件,讀取這個文件中的二進制數據,而後把Appmain類的類信息存放到運行時數據區的方法區中。這一過程稱爲AppMain類的加載過程。
接着,Java虛擬機定位到方法區中AppMain類的Main()方法的字節碼,開始執行它的指令。這個main()方法的第一條語句就是:Sample test1=new Sample("測試1");就是讓java虛擬機建立一個Sample實例,而且呢,使引用變量test1引用這個實例。就讓咱們來跟蹤一下Java虛擬機,看看它到底是怎麼來執行這個任務的:jvm

  • 一、 Java虛擬機直奔方法區,先找到Sample類的類型信息。結果這會兒的方法區裏尚未Sample類。因而立馬加載了Sample類,把Sample類的類型信息存放在方法區裏。
  • 二、 爲一個新的Sample實例分配內存, 這個Sample實例持有着指向方法區的Sample類的類型信息的引用。而這個引用地址,就存放了在Sample實例的數據區裏。
  • 三、 在JAVA虛擬機進程中,每一個線程都會擁有一個方法調用棧,用來跟蹤線程運行中一系列的方法調用過程,棧中的每個元素就被稱爲棧幀,每當線程調用一個方法的時候就會向方法棧壓入一個新幀。這裏的幀用來存儲方法的參數、局部變量和運算過程當中的臨時數據。OK,原理講完了,就讓咱們來繼續咱們的跟蹤行動!位於「=」前的Test1是一個在main()方法中定義的變量,可見,它是一個局部變量,所以,它被會添加到了執行main()方法的主線程的JAVA方法調用棧中。而「=」將把這個test1變量指向堆區中的Sample實例,也就是說,它持有指向Sample實例的引用。

接下來,JAVA虛擬機將繼續執行後續指令,在堆區裏繼續建立另外一個Sample實例,而後依次執行它們的printName()方法。當JAVA虛擬機執行test1.printName()方法時,JAVA虛擬機根據局部變量test1持有的引用,定位到堆區中的Sample實例,再根據Sample實例持有的引用,定位到方法去中Sample類的類型信息,從而得到printName()方法的字節碼,接着執行printName()方法包含的指令。測試

相關文章
相關標籤/搜索