Java程序為了提高程序的效率,就對數據進行了不同空間的分配,具體如下:
1.棧:存放的是局部變量;
2.堆:存放的是所有new出來的東西;
3.方法區:(面向對象的東西)
4.本地方法區:存放的是和系統相關的東西,比如Windows、Linux。
5.寄存器:CPU使用的。
以下着重介紹堆和棧!
棧(stack)和堆(heap)都是JAVA在RAM中存放數據的地方。
*與C++不同,JAVA自動管理棧和堆,程序員不能直接的設置棧和堆。
棧內存:
存儲的都是局部變量,而且變量所屬的作用域一旦結束,該變量就自動釋放。
堆內存:
存儲的是數組和對象(其實數組也是對象),凡是new建立在堆中。
特點:1.每一個實體都有首地址值;
2.堆內存中的每一個變量都有默認初始化值,根據類型的不同而不同;
棧和堆在內存中的存儲方式可參考下圖:
舉例:int[] arr = new int[3];
步驟:
1,創建變量arr,且這個局部變量在主函數中,故主函數的代碼段先進棧;
2,右邊用new建立的對象是實體,故放在堆中;
3,給該對象分配一個內存地址,用來存放該對象,比如:0x0045;(堆會對其中的對象進行默認初始化)
4,將對象的地址0x0045賦給棧中的變量arr,而arr就指向堆中的這個地址(也可以作稱作引用這個地址),類似於c++中的指針。
棧的優勢:存取速度比堆要快,僅次於直接位於CPU中的寄存器。
棧的缺點:1.存在棧中的數據大小和生存期必須是確定的,缺乏靈活性。
2.棧數據在多個線程或者多個棧之間是不可以共享的。(但是,在棧內部多個值相等的變量是可以指向一個地址的)
堆的優勢:可以動態的分配內存大小,生存期也不必事先告訴編譯器,JAVA的垃圾收集器會自動收走不用的數據。
堆的缺點:由於要在運行時動態分配內存,存取速度較慢。
JAVA中的數據類型有兩種:
一.基本類型(byte,short,int,long,float,double,boolean,char)
這種類型定義的變量被稱作自動變量,自動變量存的是字面值,不是類的實例(即不是類的引用)。
比如:int a=3,long b=255L 這些字面值的數據,由於大小可知,生存期可知,出於追求速度的原因,就存在於棧中。
二.包裝類數據(如Integer,String,Double等將相應的基本數據類型包裝起來的類,這些類數據全部存在於堆中)
JAVA用new語句來顯式的告訴編譯器,在運行時才根據需要動態創建,因此比較靈活,但缺點是要占用更多的時間。
注意:包裝類的值不可修改!
--------------------------------------------------------------------------------------------------------------------------------------------
由上圖1可知,JVM的基本結構包括:類裝載器,內存區域,執行引擎,本地庫接口。
下面主要介紹一下內存區:
1.虛擬機棧
每當啟動一個新線程的時候,java虛擬機都會為它分配一個java棧,故每個線程包含一個棧區。
每個棧中的數據都是私有的,其它棧不能訪問。棧分為3個部分:基本類型變量區、執行環境上下文、操作指令區。
2.堆內存
存儲的全部是對象,每個對象包含一個與之對應的class信息-----class的目的是得到操作指令。
jvm只有一個堆區被所有線程共享,堆區中不存放基本類型和對象引用,只存放對象本身。
3.方法區
在方法區中,存儲了每個類的信息(包括類的名稱、方法、字段)、靜態變量、常量以及編譯器編譯后的代碼等。
4.本地方法棧
和虛擬機棧的作用差不多,只不過是為JVM使用到的native方法服務的。
*.在HotSopt虛擬機中直接就把本地方法棧和虛擬機棧合二為一了。
5.程序計數器
用於保存當前線程執行的內存地址。
由於JVM程序是多線程執行的,為了保證線程切換回來后,還能恢復到原先狀態,就需要一個獨立的計數器,記錄之前中斷的地方,可見程序計數器也是線程私有的。