




版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
1、【深入java虛擬機(1)】: java內(nèi)存區(qū)域與內(nèi)存溢出編程 開發(fā)技術【深入java虛擬機(1)】: java內(nèi)存區(qū)域與內(nèi)存溢出原文岀處:蘭亭風雨內(nèi)存區(qū)域java虛擬機在執(zhí)行java程序的過程中會把他所管理的內(nèi)存劃分為若干個不同的 數(shù)據(jù)區(qū)域。java虛擬機規(guī)范將jvm所管理的內(nèi)存分為以下幾個運行時數(shù)據(jù)區(qū): 程序計數(shù)器、java虛擬機棧、本地方法棧、java堆、方法區(qū)。下而詳細闡述齊 數(shù)據(jù)區(qū)所存儲的數(shù)據(jù)類型。程序計數(shù)器(program?counter?register)一塊較小的內(nèi)存空間,它是當前線程所執(zhí)行的字節(jié)碼的行號指示器,字節(jié)碼解釋 器工作時通過改變該計數(shù)器的值來選擇下一條需要執(zhí)行的字節(jié)
2、碼指令,分支、跳 轉、循環(huán)等基礎功能都要依賴它來實現(xiàn)。每條線程都有一個獨立的的程序計數(shù)器, 各線程間的計數(shù)器互不影響,因此該區(qū)域是線程私有的。當線程在執(zhí)行一個java方法時,該計數(shù)器記錄的是止在執(zhí)行的虛擬機字節(jié)碼指 令的地址,當線程在執(zhí)行的是native方法(調用本地操作系統(tǒng)方法)時,該計 數(shù)器的值為空。另外,該內(nèi)存區(qū)域是唯一一個在java虛擬機規(guī)范中么有規(guī)定任 何00m (內(nèi)存溢出:outofmemoryerror)情況的區(qū)域。java 虛擬機棧(java?virtual?machine?stacks ) 該區(qū)域也是線程私有的,它的生命周期也與線程相同。虛擬機棧描述的是j3v3 方法執(zhí)行的內(nèi)
3、存模型:每個方法被執(zhí)行的時候都會同時創(chuàng)建一個棧幀,棧它是用 于支持續(xù)虛擬機進行方法調用和方法執(zhí)行的數(shù)據(jù)結構。對于執(zhí)行引擎來講,活動 線程屮,只有棧頂?shù)臈怯行У?,稱為當前棧幀,這個棧幀所關聯(lián)的方法稱為 當前方法,執(zhí)行引擎所運行的所有字節(jié)碼指令都只針對當前棧幀進行操作。棧幀 用于存儲局部變量表、操作數(shù)棧、動態(tài)鏈接、方法返回地址和一些額外的附加信 息。在編譯程序代碼時,棧幀屮需要多大的局部變量表、多深的操作數(shù)棧都已經(jīng) 完全確定了,并口寫入了方法表的code屬性之中。因此,一個棧幀需要分配多 少內(nèi)存,不會受到程序運行期變量數(shù)據(jù)的影響,而僅僅取決于具體的虛擬機實現(xiàn)。在java虛擬機規(guī)范中,對這個區(qū)域
4、規(guī)定了兩種異常情況:1、如杲線程請求的棧深度大于虛擬機所允許的深度,將拋出 stackoverf lowerror 異常。2、如果虛擬機在動態(tài)擴展棧時無法中請到足夠的內(nèi)存空間,則拋出out of memory err or 異常。這兩種情況存在著一些互相重疊的地方:當??臻g無法繼續(xù)分配時,到底是內(nèi)存 太小,述是已使用的??臻g太大,其本質上只是對同一件事情的兩種描述而已。 在單線程的操作屮,無論是由于棧幀太大,還是虛擬機??臻g太小,當??臻g無 法分配時,虛擬機拋出的都是stackoverf lowerror異常,而不會得到 outormemoryerror異彳f。而在多線程環(huán)境下,則會拋出out
5、ofmemoryerror異常。下面詳細說明棧幀中所存放的各部分信息的作用和數(shù)據(jù)結構。1、局部變量表局部變量表是一組變量值存儲空間,用于存放方法參數(shù)和方法內(nèi)部定義的局部變 量,其中存放的數(shù)據(jù)的類型是編譯期可知的各種基木數(shù)據(jù)類型、對象引用(reference)和returnaddress類型(它指向了條字節(jié)碼指令的地址)。局 部變量表所需的內(nèi)存空間在編譯期間完成分配,即在java程序被編譯成class 文件時,就確定了所需分配的最大局部變量表的容量。當進入一個方法時,這個 方法需要在棧屮分配多大的局部變量空間是完全確定的,在方法運行期間不會改 變局部變量表的大小。局部變量表的容量以變量槽(slo
6、t)為最小單位。在虛擬機規(guī)范屮并沒有明確指 明一個slot應占用的內(nèi)存空間大?。ㄔ试S其隨著處理器、操作系統(tǒng)或虛擬機的 不同而發(fā)生變化),一個slot可以存放一個32位以內(nèi)的數(shù)據(jù)類型:boolean, byte、 char> short> int、 float、 referenee 和 returnaddresss。 referenee 是對彖的引用類型,returnaddress是為字節(jié)指令服務的,它執(zhí)行了一條字節(jié)碼 指令的地址。對于64位的數(shù)據(jù)類型(long和double),虛擬機會以高位在前的 方式為其分配兩個連續(xù)的slot空間。虛擬機通過索引定位的方式使用局部變量表,索引值的
7、范圍是從0開始到局部變 量表最大的slot數(shù)量,對于32位數(shù)據(jù)類型的變量,索引n代表第n個slot, 對于64位的,索引n代表第n和第n+1兩個slot。在方法執(zhí)行時,虛擬機是使用同部變量表來完成參數(shù)值到參數(shù)變量列表的傳遞過 程的,如果是實例方法(非static),則局部變量表中的第0位索引的slot默 認是用于傳遞方法所屈對彖實例的引用,在方法屮可以通過關鍵字“this”來訪 問這個隱含的參數(shù)。其余參數(shù)則按照參數(shù)表的順序來排列,占用從1開始的局部 變量slot,參數(shù)表分配完畢后,再根據(jù)方法體內(nèi)部定義的變量順序和作用域分 配其余的sloto局部變量表中的slot是可重用的,方法體中定義的變量,
8、作用域并不一定會覆 蓋整個方法體,如果當前字節(jié)碼pc計數(shù)器的值已經(jīng)超過了某個變量的作用域, 那么這個變量對應的slot就可以交給其他變量使用。這樣的設計不僅僅是為了 節(jié)省空間,在某些情況下slot的復用會直接影響到系統(tǒng)的而垃圾收集行為。2、操作數(shù)棧操作數(shù)棧又常被稱為操作棧,操作數(shù)棧的最人深度也是在編譯的時候就確定了。 32位數(shù)據(jù)類型所占的棧容量為1, 64為數(shù)據(jù)類型所占的棧容量為2。當一個方法 開始執(zhí)行時,它的操作棧是空的,在方法的執(zhí)行過程屮,會右各種字節(jié)碼指令(比 如:加操作、賦值元算等)向操作棧中寫入和提取內(nèi)容,也就是入棧和出棧操作。java虛擬機的解釋執(zhí)行引擎稱為“基于棧的執(zhí)行引擎”,其
9、小所指的“?!本?是操作數(shù)棧。因此我們也稱java虛擬機是基于棧的,這點不同于android虛擬 機,android虛擬機是基于寄存器的?;跅5闹噶罴钪饕膬?yōu)點是可移植性強,主要的缺點是執(zhí)行速度相對會慢 些;而由于寄存器由碩件直接提供,所以基于寄存器指令集最主要的優(yōu)點是執(zhí)行 速度快,主要的缺點是可移植性差。3、動態(tài)連接每個棧幀都包含一個指向運行時常量池(在方法區(qū)中,后面介紹)中該棧幀所屬 方法的引用,持冇這個引用是為了支持方法調用過程屮的動態(tài)連接。class文件 的常量池中存在有大量的符號引用,字節(jié)碼中的方法調用指令就以常量池中指向 方法的符號引用為參數(shù)。這些符號引用,一部分會在類加載階段
10、或第一次使用的 時候轉化為直接引用(如final、static域等),稱為靜態(tài)解析,另一部分將在 每一次的運行期間轉化為直接引用,這部分稱為動態(tài)連接。4、方法返回地址當一個方法被執(zhí)行后,有兩種方式退出該方法:執(zhí)行引擎遇到了任意一個方法返 回的字節(jié)碼指令或遇到了異常,并冃該異常沒有在方法體內(nèi)得到處理。無論采用 何種退出方式,在方法退出之后,都需要返冋到方法被調用的位置,程序才能繼 續(xù)執(zhí)行。方法返回時可能需要在棧幀中保存一些信息,用來幫助恢復它的上層方 法的執(zhí)行狀態(tài)。一般來說,方法正常退出時,調用者的pc計數(shù)器的值就可以作 為返冋地址,棧幀中很可能保存了這個計數(shù)器值,而方法異常退出時,返冋地址 是
11、要通過異常處理器來確定的,棧幀屮一般不會保存這部分信息。方法退出的過程實際上等同于把當前棧幀出站,因此退出時可能執(zhí)行的操作有: 恢復上層方法的局部變量表和操作數(shù)棧,如果有返回值,則把它壓入調用者棧幀 的操作數(shù)棧中,調整pc計數(shù)器的值以指向方法調用指令后面的一條指令。本地方法棧(native?method?stacks)該區(qū)域與虛擬機棧所發(fā)揮的作用非常相似,只是虛擬機棧為虛擬機執(zhí)行java方 法服務,而木地方法棧則為使用到的木地操作系統(tǒng)(native)方法服務。java堆(java?heap)java?heap是java虛擬機所管理的內(nèi)存中最大的一塊,它是所有線程共享的一 塊內(nèi)存區(qū)域。幾乎所有的
12、對象實例和數(shù)組都在這類分配內(nèi)存。java?heap是垃圾 收集器管理的主要區(qū)域,因此很多吋候也被稱為“gc堆”。根據(jù)java虛擬機規(guī)范的規(guī)定,java堆可以處在物理上不連續(xù)的內(nèi)存空間中,只 要邏輯上是連續(xù)的即可。如果在堆屮沒冇內(nèi)存可分配時,并月堆也無法擴展時, 將會拋111 outofmemoryerror 異常。方法區(qū)(method?area)方法區(qū)也是各個線程共享的內(nèi)存區(qū)域,它用于存儲已經(jīng)被虛擬機加載的類信息、 常量、靜態(tài)變量、即時編譯器編譯后的代碼等數(shù)據(jù)。方法區(qū)域又被稱為“永久 代”,但這僅僅對j' sun hotspot來講,jrockit和ibm j9虛擬機中并不存在 永久代
13、的概念。java虛擬機規(guī)范把方法區(qū)描述為java堆的一個邏輯部分,而口 它和java?heap 樣不需要連續(xù)的內(nèi)存,可以選擇固定大小或可擴展,另夕卜,虛 擬機規(guī)范允許該區(qū)域可以選擇不實現(xiàn)垃圾回收。相對而言,垃圾收集行為在這個 區(qū)域比較少出現(xiàn)。該區(qū)域的內(nèi)存回收目標主耍針是對廢棄常量的和無用類的回 收。運行時常量池是方法區(qū)的一部分,class文件中除了冇類的版本、字段、方 法、接口等描述信息外,還有一項信息是常量池(class文件常量池),用于存 放編譯器生成的各種字面量和符號引用,這部分內(nèi)容將在類加載后存放到方法區(qū) 的運行吋常量池中。運行時常量池相對于class文件常量池的另一個重要特征是 具備
14、動態(tài)性,java語言并不要求常量一定只能在編譯期產(chǎn)生,也就是并非預置 入class文件屮的常量池的內(nèi)容才能進入方法區(qū)的運行時常量池,運行期間也可 能將新的常量放入池中,這種特性被開發(fā)人員利用比較多的是string類的 intern ()方法。根據(jù)java虛擬機規(guī)范的規(guī)定,當方法區(qū)無法滿足內(nèi)存分配需求時,將拋出 outofmemoryerror 異常。直接內(nèi)存(direct memory)直接內(nèi)存并不是虛擬機運行時數(shù)據(jù)區(qū)的一部分,也不是java虛擬機規(guī)范中定義 的內(nèi)存區(qū)域,它直接從操作系統(tǒng)中分配,因此不受java堆大小的限制,但是會 受到本機總內(nèi)存的大小及處理器尋址空間的限制,因此它也可能導致
15、outofmcmoryerror異常出現(xiàn)。在jdk1. 4中新引入了 ni0機制,它是一,種基于通 道與緩沖區(qū)的新1/0方式,可以直接從操作系統(tǒng)屮分配直接內(nèi)存,即在堆外分配 內(nèi)存,這樣能在一些場景中提高性能,因為避免了在java堆和native堆中來回 復制數(shù)據(jù)。關丁 ni0的詳細使用可以參考我的java網(wǎng)絡編程系列中關于ni0的 相關文章。內(nèi)存溢出下面給出個內(nèi)存區(qū)域內(nèi)存溢出的簡單測試方法內(nèi)存區(qū)域內(nèi)存溢出的測試方法java 堆無限循環(huán)地n卵對象出來,在l“t中保存引用,以不被垃圾收集器回 收。另外,該區(qū)域也有可能會發(fā)生內(nèi)存泄露(memory leak), 出現(xiàn)間題時,要注意區(qū)別。方法區(qū)生成大壘
16、的動態(tài)類,或無線循環(huán)調用string的intern ()方法產(chǎn)生不 同的string對象實例,并在list中保存其引用,以不被垃圾收集器回 收。后者測試常壘池,前者測試方法區(qū)的非常壘池部分。虛擬機棧和 本地方法棧單線程多線程翅歸調用一個簡單的方法: 如不斷累積的方法。會拋出 stackoverf lowerrorv*vw*v*v*v*v*vvv/v*v*v*v*v*v*v*v*v*無線循環(huán)地創(chuàng)建線程,芥未每個線 程無限循環(huán)地増加內(nèi)存。會拋出 outof m einoryerr or這里冇一點要重點說明,在多線程情況下,給每個線程的棧分配的內(nèi)存越大,反 而越容易產(chǎn)生內(nèi)存溢出異常。操作系統(tǒng)為每個進
17、程分配的內(nèi)存是冇限制的,虛擬 機提供了參數(shù)來控制java堆和方法區(qū)這兩部分內(nèi)存的最大值,忽略掉程序計數(shù) 器消耗的內(nèi)存(很小),以及進程木身消耗的內(nèi)存,剩下的內(nèi)存便給了虛擬機棧 和本地方法棧,每個線程分配到的棧容量越人,可以建立的線程數(shù)量自然就越少。 因此,如杲是建立過多的線程導致的內(nèi)存溢出,在不能減少線程數(shù)的情況廠就 只能通過減少最大堆和每個線程的棧容量來換取更多的線程。另外,由于java堆內(nèi)也可能發(fā)生內(nèi)存泄露(iemory leak),這里簡要說明一下 內(nèi)存泄露和內(nèi)存溢出的區(qū)別: 內(nèi)存泄露是指分配出去的內(nèi)存沒有被冋收冋來,由于失去了對該內(nèi)存區(qū)域的控 制,因而造成了資源的浪費。jqvqm般不會
18、產(chǎn)生內(nèi)存泄露,因為有垃圾回收 器自動回收垃圾,但這也不絕對,當我們new t對象,并保存了其引用,但是后 面一直沒用它,而垃圾回收器乂不會去回收它,這邊會造成內(nèi)存泄露,內(nèi)存溢出是指程序所需要的內(nèi)存超出了系統(tǒng)所能分配的內(nèi)存(包括動態(tài)擴展)的 上限。對象實例化分析? ?對內(nèi)存分配情況分析最常見的示例便是對象實例化:object obj = new object();這段代碼的執(zhí)行會涉及java棧、java堆、方法區(qū)三個最重要的內(nèi)存區(qū)域。假設 該語句出現(xiàn)在方法體中,及時對jvm虛擬機不了解的java使用這,應該也知道 obj會作為引用類型(reference)的數(shù)據(jù)保存在java棧的本地變量表中,而會 在java堆中保存該引用的實例化對象,但町能并不知道,java堆中還必須包含 能查找到此對象類型數(shù)據(jù)的地址信息(如對象類型、父類、實現(xiàn)的接口、方法等), 這些類型數(shù)據(jù)則保存在方法區(qū)中o另外,由于reference類型在java虛擬機規(guī)范里面只規(guī)定了一個指向對彖的引 用,并沒有定義這個引用應該通過哪種方
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 產(chǎn)品生命周期管理
- 2025-2030減肥裝置行業(yè)市場現(xiàn)狀供需分析及投資評估規(guī)劃分析研究報告
- 2025-2030全球磁性槽楔行業(yè)發(fā)展動態(tài)及投資前景展望研究報告
- 2025-2030全球及中國鋰離子電動自行車行業(yè)市場現(xiàn)狀供需分析及投資評估規(guī)劃分析研究報告
- 2025-2030全球及中國蜜月旅游行業(yè)市場現(xiàn)狀供需分析及投資評估規(guī)劃分析研究報告
- 2025-2030全球及中國電致變色存儲器件行業(yè)市場現(xiàn)狀供需分析及投資評估規(guī)劃分析研究報告
- 2025-2030全球及中國電信網(wǎng)絡改造中的SDN和NFV技術行業(yè)市場現(xiàn)狀供需分析及投資評估規(guī)劃分析研究報告
- 2025-2030全球及中國混合軸帶發(fā)電機行業(yè)供需現(xiàn)狀與需求量研究報告
- 2025-2030全球及中國有益昆蟲行業(yè)市場現(xiàn)狀供需分析及市場深度研究發(fā)展前景及規(guī)劃可行性分析研究報告
- 2025-2030全球及中國改性松香行業(yè)市場現(xiàn)狀供需分析及投資評估規(guī)劃分析研究報告
- 《社會主義核心價值觀》優(yōu)秀課件
- 髖關節(jié)的解剖-課件
- 公路工程施工現(xiàn)場安全檢查手冊
- 幼兒園繪本故事:《十二生肖》 課件
- (完整版)人教版小學3-6年級英語單詞表-可直接打印
- 一例心肌梗塞患者的病例討論培訓課件
- GB∕T 13171.2-2022 洗衣粉 第2部分:試驗方法
- 楷書(課件)課件
- 工程監(jiān)理部人員分工與職責
- 課程設計 CA6140撥叉說明書
- 成語故事杞人憂天PPT教案
評論
0/150
提交評論