摘要:虛擬機運行時數據區分為以下幾個部分。程序計數器也是在虛擬機規范中唯一沒有規定任何異常情況的區域。在方法運行期間不會改變局部變量表的大小。長度在位和位的虛擬機中,分別為官方稱它為。
Java虛擬機運行時數據區 詳解 2.1 概述
本文參考的是周志明的 《深入理解Java虛擬機》第二章 ,為了整理思路,簡單記錄一下,方便后期查閱。
2.2 運行時數據區域Java虛擬機在Java程序運行時會將內存區域劃分成若干個不同的區域,各自負責不同的職責,這些區域都有各自的用途。
Java虛擬機運行時數據區分為以下幾個部分。
方法區、虛擬機棧、本地方法棧、堆、程序計數器,如下圖所示:
圖片來源于網絡如有侵權請私信刪除2.2.1 程序計數器
程序計數器是一塊較小的內存空間,可以看作當前線程所執行的字節碼行號指示器。需要注意以下幾點內容:
程序計數器是線程私有,各線程之間互不影響。
在任何一個確定的時刻,一個處理器都只會執行一條線程中的指令。
如果正在執行java方法,計數器記錄的是正在執行的虛擬機字節碼指令地址。
如果是native方法,則計數器值為空(native 方法 指得就是Java程序調用了非Java代碼,算是一種引入其它語言程序的接口)。
程序計數器也是在Java虛擬機規范中唯一沒有規定任何OutOfMemoryError異常情況的區域。
2.2.2 java虛擬機棧可通過參數 棧幀是方法運行期的基礎數據結構棧容量可由-Xss設置
Java虛擬機棧是線程私有的,它的生命周期與線程相同。
每一個方法被調用直至執行完成的過程,就對應著一個棧幀在虛擬機棧中從入棧到出棧的過程。
虛擬機棧是執行Java方法的內存模型(也就是字節碼)服務:每個方法在執行的同時都會創建一個棧幀,用于存儲 局部變量表、操作數棧、動態鏈接、方法出口等信息。
局部變量表:32位變量槽,存放了編譯期可知的各種基本數據類型、對象引用、returnAddress類型。
操作數棧:基于棧的執行引擎,虛擬機把操作數棧作為它的工作區,大多數指令都要從這里彈出數據、執行運算,然后把結果壓回操作數棧。
動態連接:每個棧幀都包含一個指向運行時常量池(方法區的一部分)中該棧幀所屬方法的引用。持有這個引用是為了支持方法調用過程中的動態連接。Class文件的常量池中有大量的符號引用,字節碼中的方法調用指令就以常量池中指向方法的符號引用為參數。這些符號引用一部分會在類加載階段或第一次使用的時候轉化為直接引用,這種轉化稱為靜態解析。另一部分將在每一次的運行期間轉化為直接應用,這部分稱為動態連接
方法出口:返回方法被調用的位置,恢復上層方法的局部變量和操作數棧,如果無返回值,則把它壓入調用者的操作數棧。
局部變量表所需的內存空間在編譯期間完成分配,當進入一個方法時,這個方法需要在幀中分配多大的局部變量空間是完全確定的。
在方法運行期間不會改變局部變量表的大小。主要存放了編譯期可知的各種基本數據類型、對象引用 (reference類型)、returnAddress類型)。
java虛擬機棧,規定了兩種異常狀況:如果線程請求的深度大于虛擬機所允許的深度,將拋出StackOverflowError異常。
如果虛擬機棧動態擴展,而擴展時無法申請到足夠的內存,就會拋出OutOfMemoryError異常。
2.2.3 本地方法棧可通過參數 棧容量可由-Xss設置
虛擬機棧為虛擬機執行Java方法(也就是字節碼)服務。
本地方法棧則是為虛擬機使用到的Native方法服務。有的虛擬機(譬如Sun HotSpot虛擬機)直接就把本地方法棧和虛擬機棧合二為一。
2.2.4 java堆可通過參數 -Xms 初始堆大小和-Xmx 最大堆大小-Xmn 新生代` 設置
Java堆是被所有線程共享,是Java虛擬機所管理的內存中最大的一塊 Java堆在虛擬機啟動時創建。
Java堆唯一的目的是存放對象實例,幾乎所有的對象實例和數組都在這里。
Java堆為了便于更好的回收和分配內存,可以細分為,新生代和老年代
**再細致一點的有Eden空間、From Survivor空間、To Survivor區**。
新生代:包括Eden區、From Survivor區、To Survivor區,系統默認大小Eden:Survivor=8:1:1。
老年代:在年輕代中經歷了N次垃圾回收后仍然存活的對象,就會被放到老年代中。因此,可以認為老年代中存放的都是一些生命周期較長的對象。
Survivor空間等Java堆可以處在物理上不連續的內存空間中,只要邏輯上是連續的即可(就像我們的磁盤空間一樣。在實現時,既可以實現成固定大小的,也可以是可擴展的)。
據Java虛擬機規范的規定,當方法區無法滿足內存分配需求時,將拋出OutOfMemoryError異常。
2.2.5 方法區可通過參數-XX:MaxPermSize設置
線程共享內存區域,用于儲存已被虛擬機加載的類信息、常量、靜態變量,即編譯器編譯后的代碼,方法區也稱持久代(Permanent Generation)。
雖然Java虛擬機規范把方法區描述為堆的一個邏輯部分,但是它卻有一個別名叫做Non-Heap(非堆),目的應該是與Java堆區分開來。
如何實現方法區,屬于虛擬機的實現細節,不受虛擬機規范約束。
方法區主要存放java類定義信息,與垃圾回收關系不大,方法區可以選擇不實現垃圾回收,但不是沒有垃圾回收。
方法區域的內存回收目標主要是針對常量池的回收和對類型的卸載。
運行時常量池,也是方法區的一部分,虛擬機加載Class后把常量池中的數據放入運行時常量池。
2.2.6 運行時常量池可通過參數-XX:PermSize和-XX:MaxPermSize設置
常量池(Constant Pool):常量池數據編譯期被確定,是Class文件中的一部分。存儲了類、方法、接口等中的常量,當然也包括字符串常量。
字符串池/字符串常量池(String Pool/String Constant Pool):是常量池中的一部分,存儲編譯期類中產生的字符串類型數據。
運行時常量池(Runtime Constant Pool):方法區的一部分,所有線程共享。虛擬機加載Class后把常量池中的數據放入到運行時常量池。常量池:可以理解為Class文件之中的資源倉庫,它是Class文件結構中與其他項目資源關聯最多的數據類型。
常量池中主要存放兩大類常量:字面量(Literal)和符號引用(Symbolic Reference)。
字面量:文本字符串、聲明為final的常量值等;。
符號引用:類和接口的完全限定名(Fully Qualified Name)、字段的名稱和描述符(Descriptor)、方法的名稱和描述符。
JDK1.6之前字符串常量池位于方法區之中。
JDK1.7字符串常量池已經被挪到堆之中。
2.2.7 直接內存可通過-XX:MaxDirectMemorySize指定,如果不指定,則默認與Java堆的最大值(-Xmx指定)一樣。
直接內存(Direct Memory)并不是虛擬機運行時數據區的一部分,也不是Java虛擬機規范中定義的內存區域,但是這部分內存也被頻繁地使用,而且也可能導致OutOfMemoryError異常出現。
2.3 hotspot虛擬機對象探秘 2.3.1 對象的創建主要探討HotSpot虛擬機在Java堆中對象分配、布局和訪問的全過程
虛擬機遇到new指令時
首先去檢查這個指令的參數能否在常量池中定位到一個類的符號引用,并且檢查引用代表的類是否已被加載、解析和初始化過。如果沒有,則執行類加載過程(第7章 虛擬機類加載機制)。
加載檢查通過后,分配內存(內存在類加載完成后便可完全確定)。
內存分配完成后,虛擬機對對象進行必要的設置,如對象是哪個類的實例、如何找到類的元數據信息等(都放在對象的對象頭中)。
從虛擬機角度看,一個新的對象產生了,但從java程序視角看,對象創建才剛剛開始,因為
對象在內存中存儲的布局可以分為3塊區域:對象頭、實例數據、對齊填充
對象頭包含兩部分(Header)
存儲對象自身的 運行時數據,如哈希碼、GC分代年齡等。長度在32位和64位的虛擬機中,分別為32bit、 64bit,官方稱它為“Mark Word”。
類型指針,對象指向它的類元數據的指針,虛擬機通過這個指針來確定這個對象是哪個類的實例。
注:如果對象是一個java數組,對象頭中還必須有一塊記錄數據長度的數據
實例數據(InstanceData)
對象真正存儲的有用信息,也是程序中定義的各種類型的字段內容。
對齊填充(Padding)
由于HotSpot虛擬機要求對象的起始地址必須是8字節的整數倍,通俗的說,就是對象大小必須是8字節的整數倍。對象頭正好是8字節的倍數。當實例數據部分沒有對齊時,需要通過對齊填充來補全。
2.3.3 對象的訪問定位Java程序通過棧上的reference數據來操作堆上的具體對象。
不同虛擬機實現的對象訪問方式會有所不同,目前主流的訪問方式有兩種:使用句柄和直接指針。
使用句柄 是間接訪問,優點是reference中存儲的是穩定的句柄地址,對象移動時只會改變句柄中的實例數據指針。
使用直接指針 是直接訪問,優點就是速度快。
最后上一張本章結構圖圖片來源于網絡如有侵權請私信刪除
《深入理解Java虛擬機:JVM高級特性與最佳實踐_周志明.高清掃描版.pdf》
下載地址:鏈接:http://pan.baidu.com/s/1miBQCBY 密碼:9kbn
推薦閱讀《深入理解Java虛擬機》(一)Java虛擬機發展史
《深入理解Java虛擬機》(二)Java虛擬機運行時數據區
《深入理解Java虛擬機》(三)垃圾收集器與內存分配策略
《深入理解Java虛擬機》(四)虛擬機性能監控與故障處理工具
《深入理解Java虛擬機》(五)JVM調優 - 工具
《深入理解Java虛擬機》(六)堆內存使用分析,GC 日志解讀
Contact作者:鵬磊
出處:http://www.ymq.io
Email:admin@souyunku.com
版權歸作者所有,轉載請注明出處
Wechat:關注公眾號,搜云庫,專注于開發技術的研究與知識分享
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/67529.html
摘要:虛擬機在執行程序的過程中會把它所管理的內存劃分為若干個不同的數據區域。棧幀棧幀是用于支持虛擬機進行方法調用和方法執行的數據結構,它是虛擬機運行時數據區中的虛擬機棧的棧元素。棧幀的概念結構如下運行時數據區腦圖高 這里我們先說句題外話,相信大家在面試中經常被問到介紹Java內存模型,我在面試別人時也會經常問這個問題。但是,往往都會令我比較尷尬,我還話音未落,面試者就會背誦一段(Java虛擬...
摘要:抽時間重新讀了一遍深入理解一書。驗證確保文件的字節流中包含的信息符合當前虛擬機的要求,并且不會危害虛擬機自身的安全??梢娦钥梢娦允侵府斠粋€線程修改了共享變量的值,其他線程能夠立即得知這個修改。 抽時間重新讀了一遍《深入理解JVM》一書。以下為摘錄內容。 1 java內存區域 showImg(https://segmentfault.com/img/bVboDgk?w=617&h=365...
摘要:虛擬機運行時數據區虛擬機在執行程序的過程中會把它管理的內存劃分為若干個不同的數據區域。此內存區域是唯一一個在虛擬機規范中沒有規定任何情況的區域。 showImg(https://segmentfault.com/img/bVbvueY?w=1600&h=800); java虛擬機運行時數據區 java虛擬機在執行java程序的過程中會把它管理的內存劃分為若干個不同的數據區域。根據《Ja...
摘要:虛擬機發展史注本文大部分摘自深入理解虛擬機第二版作為一名開發人員,不能局限于語言規范,更需要對虛擬機規范有所了解。虛擬機規范有多種實現,其中是和中所帶的虛擬機,也是目前使用范圍最廣的虛擬機。世界第一款商用虛擬機。號稱世界上最快的虛擬機。 Java虛擬機發展史 注:本文大部分摘自《深入理解Java虛擬機(第二版)》 作為一名Java開發人員,不能局限于Java語言規范,更需要對Java虛...
摘要:深入理解虛擬機高級特性與最佳實踐第二版讀書筆記與常見面試題總結本節常見面試題介紹下內存區域運行時數據區。運行時數據區域虛擬機在執行程序的過程中會把它管理的內存劃分成若干個不同的數據區域。 《深入理解Java虛擬機:JVM高級特性與最佳實踐(第二版》讀書筆記與常見面試題總結 本節常見面試題: 介紹下Java內存區域(運行時數據區)。 對象的訪問定位的兩種方式。 1 概述 對于Java...
閱讀 811·2023-04-25 20:18
閱讀 2092·2021-11-22 13:54
閱讀 2527·2021-09-26 09:55
閱讀 3857·2021-09-22 15:28
閱讀 2969·2021-09-03 10:34
閱讀 1710·2021-07-28 00:15
閱讀 1629·2019-08-30 14:25
閱讀 1281·2019-08-29 17:16