Java中棧、堆和常量池

Java內存分配主要包括如下幾個區域:

寄存器

    最快的存儲區, 由編譯器根據需求進行分配,咱們在程序中沒法控制.。html

    存放基本類型的變量數據和對象的引用(就是一個名字),對象自己不存放在棧中,而是存放在堆或者常量池中。棧內存歸屬於單個線程,每一個線程都會有一個棧內存,其存儲的變量只能在其所屬線程中可見,即棧內存能夠理解成線程的私有內存。棧區內存由編譯器自動分配釋放,具體方法執行結束以後,系統自動釋放JVM內存資源。java

    存放全部new出來的對象或數組。堆內存中的對象對全部線程可見,能夠被全部線程訪問。jvm不定時查看堆中的對象,若是沒有引用指向這個對象就回收。數組

方法區

    只是JVM規範中定義的一個概念,用於存儲類信息、常量池、靜態變量、JIT編譯後的代碼等數據,具體放在哪裏,不一樣的實現能夠放在不一樣的地方。而永久代Hotspot虛擬機特有的概念,是方法區的一種實現,別的JVM都沒有這個東西。    jvm

靜態域

    存放靜態成員(static定義的) 。spa

常量池

    存放字符串常量和基本類型常量(public static final)。線程

非RAM(隨機存取存儲器)存儲

    硬盤等永久存儲空間。code

    

    這裏咱們主要關心棧,堆和常量池,對於棧和常量池中的對象能夠共享,對於堆中的對象不能夠共享。棧中的數據大小和生命週期是能夠肯定的,當沒有引用指向數據時,這個數據就會消失。堆中的對象的由垃圾回收器負責回收,所以大小和生命週期不須要肯定,具備很大的靈活性。 htm

1.聲明和實例化

聲明:A a=null ,聲明一個A類的對象a,a放在棧中。對象

實例化:a=new A() ,實例化這個對象a,new A() 放在堆中。blog

2. String s=newString("a")和Strings=」a」建立了幾個對象?

    String s= newString("a")建立了兩個對象,一個是在常量池中,一個是在堆內存中,常量池的爲"a",堆內存中爲new String()。變量s指向該new string()對象,而該對象又指向在常量池中的字符串常量」a」。注意的是,在new的時候java虛擬機先去內存的常量池中查找」a」這個對象,若是有就不建立了,直接把堆中的對象指向該字符串。

    String s="a"的意思就是在棧中建立一個字符串類型的變量s,而且變量s直接指向常量池中的字符串對象」a」,省去了中間的堆內存中的對象。注意的是,String s = "a",這行代碼被執行的時候,java虛擬機首先在字符串池中查找是否已經存在了值爲"a"這麼一個對象,它的判斷依據是String類equals(Object obj)方法的返回值。若是有,則再也不建立新的對象,直接返回已存在對象的引用;若是沒有,則先建立這個對象,而後把它加入到字符串池中,再將它的引用返回。

String s1=」china」

String s2=」china」

String s3=」england」

String s4=new String(「china」)

String s5=new String(「england」)

    對於字符串,其對象的引用(這裏指:s1,s2,s3,s4,s5)都是存儲在棧中的,若是是編譯期已經建立好(直接用雙引號定義的)的就存儲在常量池中,若是是運行期new出來的(一旦new就會開闢新的堆內存)才存儲在堆中。對於equals相等的字符串,在常量池中永遠只有一份,在堆中有多份。

3. 數據存放位置

int s1=6;                         s1存放在棧中;6存放在常量池

char s2 = 'g';                    s2存放在棧中;'g'存放在常量池

boolean flag = true;              flag存放在棧中;true存放在常量池

byte b = 6;                       b存放在棧中;6存放在常量池

String s3 = "china";              s3存放在棧中;"china"存放在常量池

String s4= new String("abc");     s4存放在棧中;new String()存放在堆中;"abc"存放在常量池中

注意:

    棧(stack):主要保存基本類型(或者叫內置類型)(char、byte、short、int、long、float、double、boolean)和對象的引用,數據能夠共享,速度僅次於寄存器(register),快於堆。 

相關文章
相關標籤/搜索