JVM整體示意圖:
程序計數器:
- 程序計數器是一塊較小的內存空間,它可以看作是當前線程執行行的字節碼的行號指示器(goto可以看作是按照這個行號跳轉);
- 程序計數器處於線程獨佔區,每一個線程都有一份;
- 如果線程執行的是Java方法,這個計數器記錄的是正在執行的虛擬機字節碼指令的地址。如果正在執行的是native方法,這個計數器的值爲undefined;
- 此區域是唯一一個在Java虛擬機規範中沒有規定任何OutOfMemoryError情況的區域。
Java虛擬機棧:
- 虛擬機棧描述的是Java方法執行的動態內存模型
- 棧幀
- 每個方法執行,都會創建一個棧幀,這個棧幀伴隨着方法從創建到執行完成;
- 用於存儲局部變量表,操作數棧,動態鏈接,方法出口等;
- 局部變量表
- 存放編譯器可知的各種基本數據類型,引用類型,returnAddress類型;
- 局部變量表的內存空間在編譯期完成分配,當進入一個方法時,這個方法需要在棧幀中分配多少內存是固定的,在方法運行期間是不會改變局部變量表的大小的;
- 局部變量表中存放的是一個對象的引用,所以說創建對象也不會改變它的大小(引用是一個地址)
- 虛擬機棧的大小
- 會拋出StackOverflowError
- 不限定虛擬機棧的大小會隨着方法的入棧最終導致OutOfMemoryError
本地方法棧:
- 本地方法棧和虛擬機棧是很類似的;
- 區別
- Java虛擬機棧是爲Java方法來服務的;
- 本地方法棧是爲native方法來服務的;
- 它也一樣有棧幀、局部變量表這些東西 ;
Java堆:
- Java堆就是用來存儲對象實例的;
- 也是垃圾收集器管理的主要區域;
- 分爲新生代、老年代等;
- -Xmx -Xms指定堆內存大小;
方法區:
- JVM只有只有一個方法區,被所有線程共享;
- 方法區實際上也是一塊堆,只是用來存儲類,常量相關的信息;
- 用來存放程序中永遠不變或唯一的內容(類信息[Class對象]、靜態變量、字符串常量等)
- 方法虛擬機存儲加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據;
- 類的版本
- 字段
- 方法
- 接口
- 方法區和永久代
- 垃圾回收在方法區的行爲很少,回收效率低(常量池的回收,類的卸載等)
- 運行時常量池
- 運行時常量池的數據結構相當於一個HashSet,無序,不重複的
- 兩個相同的字符串引用記錄同一個地址
- String如果實在堆內存new出來的,調用string.intern()方法,如果常量池中有equals(s)的字符串,則返回該地址,如果常量池中沒有,則在常量池中創建一個,並返回該地址