久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Java內(nèi)存區(qū)域劃分,、內(nèi)存分配原理

 小米錢 2015-04-12

        運行時數(shù)據(jù)區(qū)域

        Java虛擬機在執(zhí)行Java的過程中會把管理的內(nèi)存劃分為若干個不同的數(shù)據(jù)區(qū)域。這些區(qū)域有各自的用途,,以及創(chuàng)建和銷毀的時間,,有的區(qū)域隨著虛擬機進程的啟動而存在,而有的區(qū)域則依賴線程的啟動和結束而創(chuàng)建和銷毀,。

       Java虛擬機包括下面幾個運行時數(shù)據(jù)區(qū)域:



        程序計數(shù)器

        程序計數(shù)器是一塊較小的區(qū)域,,它的作用可以看做是當前線程所執(zhí)行的字節(jié)碼的行號指示器。在虛擬機的模型里,,字節(jié)碼指示器就是通過改變程序計數(shù)器的值來指定下一條需要執(zhí)行的指令,。分支,循環(huán)等基礎功能就是依賴程序計數(shù)器來完成的,。

        由于java虛擬機的多線程是通過輪流切換并分配處理器執(zhí)行時間來完成,,一個處理器同一時間只會執(zhí)行一條線程中的指令。為了線程恢復后能夠恢復正確的執(zhí)行位置,,每條線程都需要一個獨立的程序計數(shù)器,,以確保線程之間互不影響。所以程序計數(shù)器是“線程私有”的內(nèi)存,。

        如果虛擬機正在執(zhí)行的是一個Java方法,,則計數(shù)器指定的是字節(jié)碼指令對應的地址,如果正在執(zhí)行的是一個本地方法,,則計數(shù)器指定問空undefined,。程序計數(shù)器區(qū)域是Java虛擬機中唯一沒有定義OutOfMemory異常的區(qū)域。


        Java虛擬機棧

        和程序計數(shù)器一樣也是線程私有的,,生命周期與線程相同,。虛擬機棧描述的是Java方法執(zhí)行的內(nèi)存模型:每個方法被執(zhí)行的時候都會創(chuàng)建一個棧幀用于存儲局部變量表,操作棧,,動態(tài)鏈接,,方法出口等信息。每一個方法被調用的過程就對應一個棧幀在虛擬機棧中從入棧到出棧的過程,。

        通常所說的虛擬機運行時分為棧和堆,,這里的棧指的就是虛擬機棧或者說虛擬機棧中的局部變量表部分,。

        局部變量表存放了編譯器可知的各種基本數(shù)據(jù)類型,、對象引用和returnAddress類型(指向一條字節(jié)碼指令的地址)。局部變量表所需的內(nèi)存空間在編譯器完成分配,,當進入一個方法時這個方法需要在幀中分配多大的內(nèi)存空間是完全確定的,,運行期間不會改變局部變量表的大小。(64為長度的long和double會占用兩個局部變量空間,,其他的數(shù)據(jù)類型占用一個)

        Java虛擬機??赡艹霈F(xiàn)兩種類型的異常:1. 線程請求的棧深度大于虛擬機允許的棧深度,,將拋出StackOverflowError。2.虛擬機??臻g可以動態(tài)擴展,,當動態(tài)擴展是無法申請到足夠的空間時,拋出OutOfMemory異常,。


        本地方法棧

        本地方法棧和虛擬機?;绢愃疲徊贿^Java虛擬機棧執(zhí)行的是Java代碼(字節(jié)碼),,本地方法棧中執(zhí)行的是本地方法的服務,。本地方法棧中也會拋出StackOverflowError和OutOfMemory異常。

        

       

        堆是Java虛擬機所管理的內(nèi)存中最大的一塊,。堆是所有線程共享的一塊區(qū)域,,在虛擬機啟動時創(chuàng)建。堆的唯一目的是存放對象實例,,幾乎所有的對象實例都在這里分配,,不過隨著JIT編譯器的發(fā)展和逃逸技術的成熟,棧上分配和標量替換技術使得這種情況發(fā)生著微妙的變化,,對上分配正變得不那么絕對,。

附:在Java編程語言和環(huán)境中,即時編譯器(JIT compiler,,just-in-time compiler)是一個把Java的字節(jié)碼(包括需要被解釋的指令的程序)轉換成可以直接發(fā)送給處理器的指令的程序,。當你寫好一個Java程序后,,源語言的語句將由Java編譯器編譯成字節(jié)碼,,而不是編譯成與某個特定的處理器硬件平臺對應的指令代碼(比如,Intel的Pentium微處理器或IBM的System/390處理器),。字節(jié)碼是可以發(fā)送給任何平臺并且能在那個平臺上運行的獨立于平臺的代碼,。

        Java堆是垃圾收集器管理的主要區(qū)域,所以也稱為“GC堆”,。由于現(xiàn)在的垃圾收集器基本上都是采用分代收集算法,,所以Java堆還可細分為:新生代和老生代。在細致一點可分為Eden空間,,F(xiàn)rom Survivor空間,,To Survivor空間。如果從內(nèi)存分配的角度看,,線程共享的Java堆可劃分出多個線程私有的分配緩沖區(qū),。不過無論如何劃分,都與存放內(nèi)容無關,,無論哪個區(qū)域,,都是用來存放對象實例,。細分的目的是為了更好的回收內(nèi)存或者更快的分配內(nèi)存。

        Java堆可以是物理上不連續(xù)的空間,,只要邏輯上連續(xù)即可,,主流的虛擬機都是按照可擴展的方式來實現(xiàn)的。如果當前對中沒有內(nèi)存完成對象實例的創(chuàng)建,,并且不能在進行內(nèi)存擴展,,則會拋出OutOfMemory異常。


         方法區(qū)

         方法區(qū)也是線程共享的區(qū)域,,用于存儲已經(jīng)被虛擬機加載的類信息,,常量,靜態(tài)變量和即時編譯器(JIT)編譯后的代碼等數(shù)據(jù),。Java虛擬機把方法區(qū)描述為堆的一個邏輯分區(qū),,不過方法區(qū)有一個別名Non-Heap(非堆),用于區(qū)別于Java堆區(qū),。

         Java虛擬機規(guī)范對這個區(qū)域的限制也非常寬松,,除了可以是物理不連續(xù)的空間外,也允許固定大小和擴展性,,還可以不實現(xiàn)垃圾收集,。相對而言,垃圾收集行為在這個區(qū)域是比較少出現(xiàn)的(所以常量和靜態(tài)變量的定義要多注意),。方法區(qū)的內(nèi)存收集還是會出現(xiàn),,不過這個區(qū)域的內(nèi)存收集主要是針對常量池的回收和對類型的卸載。

        一般來說方法區(qū)的內(nèi)存回收比較難以令人滿意,。當方法區(qū)無法滿足內(nèi)存分配需求時將拋出OutOfMemoryError異常,。

 

       運行時常量池

       運行時常量池是方法區(qū)的一部分,Class文件中除了有類的版本,,字段,,方法,接口等信息以外,,還有一項信息是常量池用于存儲編譯器生成的各種字面量和符號引用,,這部分信息將在類加載后存放到方法區(qū)的運行時常量池中。Java虛擬機對類的每一部分(包括常量池)都有嚴格的規(guī)定,,每個字節(jié)用于存儲哪種數(shù)據(jù)都必須有規(guī)范上的要求,,這樣才能夠被虛擬機認可,裝載和執(zhí)行,。一般來說,,除了保存Class文件中描述的符號引用外,還會把翻譯出來的直接引用也存儲在運行時常量池中,。

        運行時常量池相對于Class文件常量池的另外一個重要特征是具備動態(tài)性,,Java虛擬機并不要求常量只能在編譯期產(chǎn)生,,也就是并非預置入Class文件常量池的內(nèi)容才能進入方法區(qū)的運行時常量池中,運行期間也可將新的常量放入常量池中,。

       常量池是方法區(qū)的一部分,,所以受到內(nèi)存的限制,當無法申請到足夠內(nèi)存時會拋出OutOfMemoryError異常,。

       

       對象訪問

       對象訪問在Java語言中無處不在,,即使是最簡單的訪問,也會涉及到Java棧,,java堆,,方法區(qū)這三個最重要的內(nèi)存區(qū)域之間的關聯(lián)關系。如下面的代碼:

       Object obj = new Object();

       假設這段代碼出現(xiàn)在方法體中,,那么“Object obj”部分的語義將會反映到Java棧的本地變量表中,,作為一個reference類型的數(shù)據(jù)存在。而“new Object();”部分的語義將會反應到Java堆中,,形成一塊存儲Object類型所有實例數(shù)據(jù)值(Instance Data)的結構化內(nèi)存,,根據(jù)具體類型以及虛擬機實現(xiàn)的對象分布的不同,這塊內(nèi)存的長度是不固定的,。另外,,在JAVA堆中還必須包含能查找到此對象內(nèi)存數(shù)據(jù)的地址信息,這些類型數(shù)據(jù)則存儲在方法區(qū)中,。

       由于reference類型在Java虛擬機中之規(guī)定了指向對象的引用,,并沒有規(guī)定這個引用要通過哪種方式去定位,以及訪問到Java堆中的對象的具體位置,,因此虛擬機實現(xiàn)的對象訪問方式會有所不同,。主流的訪問方式有兩種:句柄訪問方式和直接指針。

       1. 如果使用句柄訪問方式,,Java堆中將會劃分出一塊內(nèi)存來作為句柄池,,reference中存儲的就是對象的地址,,而句柄中包含了對象實例數(shù)據(jù)和類型數(shù)據(jù)各自的具體地址信息,。

     

       2. 如果通過直接指針方式訪問,Java堆對象的布局中就必須考慮如何放置訪問類型數(shù)據(jù)的相關信息,,reference中直接存儲的就是對象的地址,。

        

        兩種方式各有優(yōu)勢,局并訪問方式最大的好處是reference中存放的是穩(wěn)定的句柄地址,,在對象被移動時,,只會改變句柄中的實例數(shù)據(jù)指針,而reference本身不需要被修改,。而指針訪問的最大優(yōu)勢是速度快,,它節(jié)省了一次指針定位的開銷,,由于對象訪問在Java中非常頻繁,一次這類開銷積少成多后也是一項非??捎^的成本,。

        具體的訪問方式都是有虛擬機指定的,虛擬機Sun HotSpot使用的是直接指針方式,,不過從整個軟件開發(fā)的范圍來看,,各種語言和框架使用句柄訪問方式的情況十分常見。


    本站是提供個人知識管理的網(wǎng)絡存儲空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導購買等信息,,謹防詐騙。如發(fā)現(xiàn)有害或侵權內(nèi)容,,請點擊一鍵舉報,。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多