1、堆的核心概述
一個JVM實例只存在一個堆內存,是Java內存管理的核心區域,在JVM啟動時創建,空間大小也確定了,是JVM管理的最大一塊內存空間。
1、堆的核心概述
一個JVM實例只存在一個堆內存,是Java內存管理的核心區域,在JVM啟動時創建,空間大小也確定了,是JVM管理的最大一塊內存空間。
《Java虛擬機規范》規定,堆可以處于物理上不連續的內存空間中,但邏輯上應該視為連續的。所有的線程共享,還可以劃分線程私有的緩沖區(Thread Local Allocation Buffer,TLAB)。所有的對象實列以及數組都應當在運行時分配在堆上,從實際使用角度看,應該是幾乎。
數組和對象可能永遠不會存儲在棧上,因為棧幀中保存引用,這個引用指向對象或者數組在堆中的位置。
方法結束后,堆中的對象在垃圾收集的時候才會被移除,是GC(Garbage Collection)執行垃圾回收的重點區域,大都使用分代垃圾收集算法。
2、新生代與老年代
存儲在JVM中的Java對象可以劃分為兩類
生命周期較短的瞬時對象,這類對象的創建和消亡都非常迅速。 生命周期非常長,某些情況能夠與JVM生命周期保持一致。
堆區進一步細分,可分為新生代(YoungGen)和老年代(OldGen),其中新生代可以細分為Eden空間,Survivor0,Survivor1空間(也叫from區和to區)。 ? 配置新時代與老年代在對結構的占比(開發中一般不調,除非確定生命周期長的對象很多。)
默認-XX:NewRatio=2,表示新時代占1,老年代占2,新生代占整個堆的1/3 可以修改-XX:NewRatio=4,表示新生代占1,老年代占4,新生代占整個堆的1/5。
HotSpot中,Eden和Survivor空間占比是8:1:1,開發人員可以通過 -XX:SurvivorRatio=N 調整空間比例,使用-XX:-UserAdaptiveSizePolicy(關自適應的內存分配策略)調整空間比例無效。
Java對象幾乎都是在Eden區創建的,80%左右的對象在新生代進行銷毀,可以使用 -Xmn 設置新生代最大內存大小,一般不設置,使用默認值。
3、棧的核心概述
不同平臺CPU架構不同,由于跨平臺性的設計,Java的指令都是根據棧來設計的。
優點是跨平臺,指令集小,編譯器容易實現,缺點是性能下降,實現同樣的功能需要更多的指令。
棧(stack):運行時單位,解決程序運行問題,即程序如何執行,如何處理數據。
堆(heap):存儲單位,解決數據存儲問題,即數據怎么放,放哪兒。
4、Java虛擬機棧是什么?
Java虛擬機棧(Java Virtual Machine Stack),早期也叫Java棧。線程在創建時會創建一個虛擬機棧,內部保存棧幀(Stack Frame),對應Java的方法調用,是線程私有的,生命周期和線程一致。
主管程序運行,保存方法局部變量(8種基本數據類型及引用對象的引用地址),部分結果,并參與方法的調用和返回。是一種快速有效的分配存儲方式,訪問速度僅次于程序計數器。會有OOM(內存溢出)問題,但不存在垃圾回收問題。
Java棧的大小可以是動態或者固定不變的。采用固定大小,每個線程的Java虛擬機棧容量可以在線程創建時獨立選定。如果請求分配的容量超過Java虛擬機棧允許的最大容量,會拋出StackOverflowError異常。
采用動態擴展,并在嘗試擴展時無法申請到足夠的內存,或者在創建新線程時沒有足夠內存去創建對應的虛擬機棧,將拋出OutOfMemloryError 異常。
5、棧(Stack)的存儲單位
棧中的數據以棧幀(Stack Frame)的格式存儲,正在執行的方法都有各自對應的棧幀,棧幀是一個內存區塊,是一個數據集,維系著方法執行過程中的各種數據信息。
JVM直接對Java棧的操作只有:入棧(壓棧、進棧)和出棧(彈棧),遵循“先進后出”/“后進先出”原則。
在一個活動的線程中,同一時間只有一個活動的棧幀,即只有當前正在執行的方法的棧幀(棧頂棧幀)是有效的,這個棧幀被稱為當前棧幀,與當前棧幀對應的方法就是當前方法,定義這個方法的類就是當前類。
執行引擎運行的字節碼指令只針對當前棧幀進行操作,如果在當前方法中調用了其它方法,對應的新棧會被創建出來,并放在棧的頂端,成為新的棧幀。
不同線程中所包含的棧幀不允許存在互相引用,即不能在一個棧幀之中引用另一個線程的棧幀。
Java方法返回函數的兩種方式:使用return指令和拋出異常,都會導致棧幀被彈出。
6、局部變量表(Local Variables Table)
局部變量表也稱為局部變量數組或本地變量表,主要用于存儲方法參數和定義在方法體內部的局部變量,這些數據包括基本數據類型、對象引用(reference),以及returnAddress類型,表建立在線程的棧上,是線程的私有數據,不存在數據安全問題。
局部變量表所需的容量大小在編譯期確定下來,并保存在方法的Code屬性的maximun local Variables數據項中,方法運行期間不會改變局部變量表的大小。
方法嵌套(如:遞歸)調用的次數由棧的大小決定。棧越大,方法嵌套調用次數越多。函數的參數和局部變量越多,局部變量表膨脹,棧幀就越大。
局部變量表中的變量只在當前方法中有效。方法執行時,虛擬機通過局部變量表完成參數數值到參數變量列表的傳遞過程。方法調用結束后,隨方法棧幀的銷毀而銷毀。
局部變量表不存在系統初始化過程,因此定義了局部變量必須人為初始化,否則無法使用。
手機瀏覽
全國
19974831731





