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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

java内存管理机制剖析(一)

發(fā)布時間:2023/12/15 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java内存管理机制剖析(一) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

最近利用工作之余學(xué)習(xí)研究了一下java的內(nèi)存管理機(jī)制,在這里記錄總結(jié)一下。

1.1 java內(nèi)存區(qū)域

當(dāng)java程序運(yùn)行時,java虛擬機(jī)會將內(nèi)存劃分為若干個不同的數(shù)據(jù)區(qū)域,這些內(nèi)存區(qū)域創(chuàng)建和銷毀的時間各不相同,所承擔(dān)的功能也不相同,他們各司其職,各盡所責(zé)。這些區(qū)域的劃分如下圖

運(yùn)行時數(shù)據(jù)區(qū)主要有五個區(qū),分別是 堆 ,方法區(qū),虛擬機(jī)棧,本地方法棧,程序計數(shù)器,下面我來一一詳細(xì)講解這五個數(shù)據(jù)區(qū)

java堆是java虛擬機(jī)管理內(nèi)存中最大的一塊,它是被所有線程共享的一塊內(nèi)存區(qū)域,在虛擬機(jī)啟動時創(chuàng)建,此內(nèi)存的唯一目的就是存放對象實例,幾乎所有的對象實例以及數(shù)組都在堆分配內(nèi)存。

java虛擬機(jī)規(guī)定,java堆可以處于物理上不連續(xù)的內(nèi)存空間中,只要邏輯上連續(xù)即可。在實現(xiàn)時,既可以實現(xiàn)固定大小的,也可以是擴(kuò)展的,可以通過配置-Xmx和-Xms來擴(kuò)展大小。如果堆中沒有內(nèi)存完成實例分配,并且堆也無法再擴(kuò)展時,將會拋出OutOfMemoryError

方法區(qū)

方法區(qū)也是被所有線程共享的一塊內(nèi)存區(qū)域,在Java虛擬機(jī)規(guī)范中,方法區(qū)是堆的邏輯組成部分,但他又被與堆區(qū)分開來,別名稱為Non-Heap,它主要的存儲內(nèi)容有下面幾點

  • 類型的完整有效名
  • 類型直接父類的完整有效名
  • 類型的修飾符(public,abstract,final的某個子集)
  • 類型的常量池
  • 域(Field)信息
  • 方法(Method)信息
  • 除了常量外的所有靜態(tài)(static)變量

總結(jié)起來就是主要用于存儲已被虛擬機(jī)加載的類信息,常量,靜態(tài)變量,編譯器編譯后的代碼等數(shù)據(jù)

這里我在介紹一下常量池,域信息和方法信息

常量池

常量池也稱為運(yùn)行時常量池(Runtime Constant Pool),用于存放編譯期生成的各種字面量和符號引用,它是這個類型用到的常量的一個有序集合,包括實際的常量(String, Integer, 和Floating point常量)和類型,域和方法的符號引用。
池中的數(shù)據(jù)項像數(shù)組項一樣,是通過索引訪問的。 因為常量池存儲了一個類類型所使用到的所有類型,域和方法的符號引用,所以它在java程序的動態(tài)鏈接中起了核心的作用

域(Field)信息

域的相關(guān)信息包括:域名; 域類型; 域修飾符(public, private, protected,static,final volatile,transient的某個子集)

方法(Method)信息

方法的相關(guān)信息包括:方法名, 方法的返回類型(或 void), 方法參數(shù)的數(shù)量和類型(有序的),方法的修飾符(public, private, protected, static, final, synchronized, native, abstract的一個子集),除了abstract和native方法外,其他方法還有保存方法的字節(jié)碼(bytecodes)操作數(shù)棧和方法棧幀的局部變量區(qū)的大小。

java虛擬機(jī)規(guī)范對方法區(qū)的限制比較寬松,除了和java堆一樣不需要連續(xù)的內(nèi)存和可以選擇固定大小或者可擴(kuò)展外,還可以選擇不是實現(xiàn)垃圾收集。垃圾收集行為在方法區(qū)也比較少出現(xiàn),當(dāng)方法區(qū)無法滿足內(nèi)存分配時,會拋出OutOfMemoryError

虛擬機(jī)棧

虛擬機(jī)棧是線程私有的,它的生命周期與線程相同,當(dāng)我們start一個線程時,jvm會為當(dāng)前線程開辟一塊虛擬機(jī)棧,當(dāng)當(dāng)前線程死亡時,線程的虛擬機(jī)棧也會銷毀。

代碼中每個方法在執(zhí)行的同時,都會創(chuàng)建一個棧幀(Stack Frame)用于存儲局部變量表,操作數(shù)棧,動態(tài)鏈接,方法出口等信息。每一個方法調(diào)用直至執(zhí)行完成的過程,就對應(yīng)著一個棧幀在虛擬機(jī)棧中入棧到出棧的過程。

局部變量表存放了編譯期可知的各種基本數(shù)據(jù)類型(boolean,byte,char,short,int,float,long,double),對象引用和returnAddreass類型

JVM對這個區(qū)域規(guī)定了兩種異常情況:如果線程請求的棧深度大于虛擬機(jī)所允許的深度,將拋出SstackOverFlowError異常;如果虛擬機(jī)??梢詣討B(tài)擴(kuò)展,如果擴(kuò)展時無法申請到足夠的內(nèi)存,就會拋出OutOfMemoryErro異常

本地方法棧

本地方法棧和虛擬機(jī)棧的作用是一樣的,只不過本地方法棧是虛擬機(jī)執(zhí)行java方法時開辟的棧,而本地方法棧是虛擬機(jī)用到Native方法時,開辟的棧。

程序計數(shù)器

程序計數(shù)器是一塊較小的內(nèi)存,它可以看作是當(dāng)前線程的字節(jié)碼的行號指示器。在虛擬機(jī)的概念模型里,字節(jié)碼解釋器工作時就是通過改變這個計數(shù)器的值來選取嚇一跳需要執(zhí)行的字節(jié)碼指令,分支,循環(huán),跳轉(zhuǎn),異常處理,線程恢復(fù)等基礎(chǔ)功能。

由于java虛擬機(jī)的多線程是通過線程輪流切換并分配處理器執(zhí)行時間的方式來實現(xiàn)的,在任何一個確定的時刻,一個處理器都只會執(zhí)行一條線程中的指令。因此,為了線程切換后能恢復(fù)到正確的執(zhí)行位置,每條線程都需要有一個獨(dú)立的程序計數(shù)器,各線程指尖計數(shù)器互不影響,獨(dú)立存儲。

1.2 對象創(chuàng)建

了解了內(nèi)存的數(shù)據(jù)區(qū)域,我們可以進(jìn)一步了解對象是如何創(chuàng)建的了。這里先通過一張流程圖一窺java的對象創(chuàng)建過程

可以看到,當(dāng)虛擬機(jī)遇到一條new指令時,首先去檢查這個指令的參數(shù)是否能在常量池中定位到一個類的符號引用,并且檢查這個符號引用代表的類是否已經(jīng)加載。如果沒有,則執(zhí)行加載。

加載完成后,便會在堆中為對象分配內(nèi)存,JVM有兩種分配方式①指針碰撞,②空閑列表,下面我詳細(xì)講講這兩種分配方式。

指針碰撞

當(dāng)java堆中內(nèi)存是整齊的,所有用過的內(nèi)存都放一邊,空閑的內(nèi)存放在另一邊,中間放著一個指針座位分界點的指示器,那所分配內(nèi)存就僅僅是把那個指針向空閑空間那邊摞動一段與對象大小相等的距離,這種分配就叫指針碰撞

空閑列表

當(dāng)Java堆的內(nèi)存并不是完整的,已分配的內(nèi)存和空閑內(nèi)存相互交錯,JVM通過維護(hù)一個列表,記錄可用的內(nèi)存塊信息,當(dāng)分配操作發(fā)生時,從列表中找到一個足夠大的內(nèi)存塊分配給對象實例,并更新列表上的記錄。這種分配方式稱為空閑列表

當(dāng)JVM所采用的垃圾收集器帶有壓縮整理功能時,java堆是規(guī)整的,這個時候會采用指針碰撞分配內(nèi)存,否則會采用空閑列表分配內(nèi)存。對象創(chuàng)建是一個非常頻繁的行為,進(jìn)行堆內(nèi)存分配時還需要考慮多線程并發(fā)問題,可能出現(xiàn)正在給對象A分配內(nèi)存,指針或記錄還未更新,對象B又同時分配到原來的內(nèi)存,解決這個問題有兩種方案:

  • 1、采用CAS保證數(shù)據(jù)更新操作的原子性;
  • 2、把內(nèi)存分配的行為按照線程進(jìn)行劃分,在不同的空間中進(jìn)行,每個線程在Java堆中預(yù)先分配一個內(nèi)存塊,稱為本地線程分配緩沖(Thread Local Allocation Buffer, TLAB);

點擊,查看更多詳情

總結(jié)

以上是生活随笔為你收集整理的java内存管理机制剖析(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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