一、JVM運行時數據區
運行時數據區.png
- 程序計數器
當前線程所執行字節碼行號指示器,唯一一個沒有OOE的區域
線程切換后能恢復到正確的執行位置 - 虛擬機棧
生命周期和線程一致,描述java方法執行的內存模型:每個方法執行時都會創建一個棧幀(Stack Frame) ,用于存儲局部變量表、操作數棧、動態鏈接、方法出入口等信息。每一個方法從調用到執行完成,就對應著一個棧幀在虛擬機棧中入棧到出棧。 - 本地方法棧
為JVM使用到的Native方法服務。 - java堆
線程共享的區域,此內存區域的唯一目的就是存放對象實例。所有對象實例及數組都要在堆上分配。
從內存回收角度:堆 = 新生代(Eden + From Survivor + To Survivor) + 老生代。
從內存分配角度:堆中可能劃分出多個線程私有的分配緩沖器(TLAB)。
-Xmx:最大可用堆空間 -Xms:初始分配空間
-Xmn:年輕代空間 -Xss:每個線程堆棧大小
- 方法區(也稱永久代)
用于存放已被JVM加載的類信息、常量、靜態變量等。
運行時常量池是方法區的一部分,對應于Class文件中的常量池
注:String.intern()
native方法,如果字符串常量池中已包含,就返回其引用,否則加入到常量池中,再返回引用。
- 1.6中,會把首次遇到的字符串復制到永久帶,返回永久代的引用
- 1.7后,intern方法不再復制,只是在常量池中記錄首次出現的引用。(估計這樣,由于永久代有引用,所以字符串不會被回收,變相成為一個常量,并且不占用永久代空間)
二、對象的創建
JVM遇到new指令:
- 首先檢查能否在常量池中定位到類的符號引用,并檢查符號引用代表的類是否已被加載,解析和初始化。
- 然后為對象分配內存
- 分配內存之后JVM會將內存空間都初始化為零值(不包括對象頭)。
- JVM對對象進行必要設置
對象是哪個類的實例、類型指針(指向元數據)、對象的Hash碼、對象的GC分代年齡、鎖狀態標志、線程持有的鎖、偏向線程id、偏向時間戳等,這些信息存放在對象頭。 -
執行<init>方法
圖片1.png