日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

JVM(周志明著深入了解JVM书归纳,新写一点就重新传一遍)

發(fā)布時間:2023/12/8 编程问答 58 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JVM(周志明著深入了解JVM书归纳,新写一点就重新传一遍) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

JVM

第2章 Java內(nèi)存區(qū)域與內(nèi)存溢出異常

運行時數(shù)據(jù)區(qū):方法區(qū)、虛擬機棧、本地方法棧、堆、程序計數(shù)器。

執(zhí)行引擎

本地庫接口

本地方法庫

I.概念

1.程序計數(shù)器(線程私有)

作用:當(dāng)前線程所執(zhí)行的字節(jié)碼的信號指示器。

由于Java虛擬機的多線程功能是通過線程輪流切換并分配處理器執(zhí)行時間的方式來實現(xiàn)的,在任何一個確定的時刻,一個處理器只會執(zhí)行一條線程中的指令。因此,為了線程切換后能恢復(fù)到正確的執(zhí)行位置,每條線程都需要有一個獨立的程序計數(shù)器,各條線程之間的計數(shù)器互不影響,獨立存儲,我們稱這類內(nèi)存區(qū)域為“線程私有”的內(nèi)存。

如果線程正在執(zhí)行一個Java方法,這個計數(shù)器記錄的是正在執(zhí)行的虛擬機字節(jié)碼指令的地址;如果正在執(zhí)行的是Native方法,這個計數(shù)器則為空(Undefined),此內(nèi)存區(qū)域是唯一一個在Java虛擬機規(guī)范中沒有規(guī)定任何OOM情況的區(qū)域

2.Java虛擬機棧(線程私有)

生命周期與線程相同。

虛擬機棧描述的是Java方法執(zhí)行的內(nèi)存模型:每個方法被執(zhí)行的時候都會同時創(chuàng)建一個棧幀用于存儲局部變量表、操作棧、動態(tài)鏈接、方法出口等信息。每一個方法被調(diào)用直至執(zhí)行完成的過程,就對應(yīng)著一個棧幀在虛擬機棧中從入棧到出棧的過程。

局部變量表所需的內(nèi)存空間在編譯期間是完全確定的,在方法運行期間不會改變局部變量表的大小。局部變量表中存放了各種基本數(shù)據(jù)類型(boolean、byte、char、short、int、float、long、double)、對象引用(reference類型,不等同于對象本身)和returnAddress類型。其中64位長度的long和double類型的數(shù)據(jù)會占用2個局部變量空間(Slot),其它只占用1個

3.本地方法棧

與虛擬機棧發(fā)揮作用相似。區(qū)別:虛擬機棧為java方法(字節(jié)碼)服務(wù);本地方法棧為虛擬機使用到的Native方法服務(wù)。(有些虛擬機將本地方法棧與虛擬機棧合二為一,本地方法區(qū)域也會拋出StackOVerflowError和OOM異常)

4.Java堆

對大多數(shù)應(yīng)用來說,Java堆是虛擬機所管理的內(nèi)存中最大的一塊。Java堆是被所有線程共享的一塊內(nèi)存區(qū)域,在虛擬機啟動時創(chuàng)建

Java堆可以分為:Eden空間、From Survivor空間、To Survivor空間等。(Eden、S1、S2)

如果堆中沒有內(nèi)存完成實例分配,并且堆也無法再擴展時,將會拋出OOM異常

5.方法區(qū)(別名:非堆)

與Java堆一樣,是各個線程共享的內(nèi)存區(qū)域。

用于存儲已被虛擬機加載的類信息、常量、靜態(tài)變量、即時編譯器變異后的代碼等數(shù)據(jù)。

當(dāng)方法區(qū)無法滿足內(nèi)存分配需求時,將拋出OOM異常

6.運行時常量池

是方法區(qū)的一部分。

Class文件中除了有類的版本、字段、方法、接口等描述的信息外,還有一項信息是常量池,用于存放編譯器生成的各種字面量和符號引用,這部分內(nèi)容將在類加載后存放到方法區(qū)的運行時常量池中。

運行時也能將新的常量放入常量池中,開發(fā)人員用得比較多的是String類的intern()方法

當(dāng)常量池?zé)o法再申請到內(nèi)存時會拋出OOM異常

7.直接內(nèi)存

不是虛擬機運行時數(shù)據(jù)區(qū)的一部分,也不是Java虛擬機規(guī)范中定義的內(nèi)存區(qū)域,但也頻繁地使用,并且也可能導(dǎo)致OOM異常

JDK4加入了NIO類,引入了異種基于通道(channel)與緩沖區(qū)(Buffer)的I/O方式,它可以使用Native函數(shù)庫直接分配堆外內(nèi)存,然后通過一個存儲在Java堆里面的DirectByteBuffer對象作為這塊內(nèi)存的引用進行操作。這樣能在一些場景中顯著提高性能,因為避免了在Java堆和Native堆中來回復(fù)制數(shù)據(jù)。

本機直接內(nèi)存的分配不會受到Java堆大小的限制,但是會受到本機總內(nèi)存(包括RAM及SWAP區(qū)或者分頁文件)的大小及處理器尋址空間的限制。分配內(nèi)存時經(jīng)常會忽略直接村內(nèi),使得各個區(qū)域的綜合大于物理內(nèi)存限制(包括物理上的和操作系統(tǒng)的限制),從而導(dǎo)致動態(tài)擴展時出現(xiàn)OOM異常

II.對象訪問

這塊自己平時就有琢磨過,在沒看任何資料的情況下,只是自己假象了2種情況,來看看真正的對象訪問機制。

對象訪問在Java中無處不在,但即使是最簡單的訪問,也會涉及到Java棧、Java堆、方法區(qū)三個最重要的內(nèi)存區(qū)域之間的關(guān)聯(lián)關(guān)系

使用句柄方式訪問:Java堆中將會劃分出一塊內(nèi)存來作為句柄池,reference中存儲的就是對象的句柄地址,而句柄中包含了對象實例數(shù)據(jù)和類型數(shù)據(jù)各自的具體地址信息。最大好處:reference中存儲的是穩(wěn)定的句柄地址,在對象被移動(垃圾回收時移動對象是非常普遍的行為)時只會改變句柄中的實例數(shù)據(jù)指針,而reference本身不需要被修改。句柄池中有兩個指針:實例數(shù)據(jù)的和類型數(shù)據(jù)的,會分別去到實例池和方法區(qū)中的對象類型數(shù)據(jù)中。

使用直接指針訪問:對象實例數(shù)據(jù)和到對象類型數(shù)據(jù)的指針是放在一起的,所以節(jié)省了一次指針定位的時間開銷,由于對象的訪問在Java中非常頻繁,因此這類開銷積少成多后也是一項非擦汗那個可觀的執(zhí)行成本。

總結(jié)

以上是生活随笔為你收集整理的JVM(周志明著深入了解JVM书归纳,新写一点就重新传一遍)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。