當我們在JVM中運行一段程序代碼,JVM初始運行的時候都會分配好Method Area(方法區(qū))和Heap(堆)
          ,而JVM每遇到一個線程,就為其分配一個Program Counter Register(程序計數(shù)器), VM Stack(虛擬機棧)和Native
          Method Stack (本地方法棧),當線程終止時,三者(虛擬機棧,本地方法棧和程序計數(shù)器)所占用的內(nèi)存空間也會被釋放掉。


          這也是為什么我把內(nèi)存區(qū)域分為線程共享和非線程共享的原因,非線程共享的那三個區(qū)域的生命周期與所屬線程相同,而線程共享的區(qū)域與JAVA程序運行的生命周期相同,所以這也是系統(tǒng)垃圾回收的場所只發(fā)生在線程共享的區(qū)域的原因。
          graph LR a(申請新內(nèi)存)-->b(eden區(qū)) b--內(nèi)存充足-->c(在eden直接分配) b--第一次內(nèi)存不足-->d(首次進行yong
          gc,YGC) d--Eden內(nèi)存活的對象復制到s1-->e(Survivor1,s1) b--第二次內(nèi)存不足-->f(再次進行YCC)
          f--eden+s1復制到s2清理eden和s1-->ff(Survivor2,s2) f--生存次數(shù)超過閾值的對象-->g(老年代)
          g--老年代空間不足時-->h(進行full gc,FGC)
          No.1 程序計數(shù)器

          程序計數(shù)器是一塊較小的內(nèi)存區(qū)域,作用可以看做是當前線程執(zhí)行的字節(jié)碼的位置指示器。分支、循環(huán)、跳轉(zhuǎn)、異常處理和線程恢復等基礎功能都需要依賴這個計算器來完成。

          No.2 虛擬機棧


          虛擬機棧也叫棧內(nèi)存,是在線程創(chuàng)建時創(chuàng)建,它的生命期是跟隨線程的生命期,線程結(jié)束棧內(nèi)存也就釋放,對于棧來說不存在垃圾回收問題,只要線程一結(jié)束,該棧就釋放了,所以不存在垃圾回收。
          它所描述的是java方法執(zhí)行的內(nèi)存模型,每個方法執(zhí)行的同時創(chuàng)建幀棧(Strack
          Frame)用于存儲局部變量表(包含了對應的方法參數(shù)和局部變量),操作棧(Operand
          Stack,記錄出棧、入棧的操作),動態(tài)鏈接、方法出口等信息,每個方法被調(diào)用直到執(zhí)行完畢的過程,對應這幀棧在虛擬機棧的入棧和出棧的過程。

          2.1、局部變量表

          局部變量表存放了編譯期可知的各種: 基本數(shù)據(jù)類型(boolean、byte、char、short、int、float、long、double)
          對象的引用(reference類型,不等同于對象本身,根據(jù)不同的虛擬機實現(xiàn),可能是一個指向?qū)ο笃鹗嫉刂返囊弥羔?br>,也可能是一個代表對象的句柄或者其他與對象相關的位置) returnAdress類型(指向下一條字節(jié)碼指令的地址)
          局部變量表所需的內(nèi)存空間:在編譯期間分配,運行期間不改變(大小固定)。

          2.2、棧幀

          棧幀是一個內(nèi)存區(qū)塊,是一個數(shù)據(jù)集,是一個有關方法(Method)和運行期數(shù)據(jù)的數(shù)據(jù)集,當一個方法 A 被調(diào)用時就產(chǎn)生了一個棧幀 F1,并被壓入到棧中,A
          方法又調(diào)用了 B 方法,于是產(chǎn)生棧幀 F2 也被壓入棧,執(zhí)行完畢后,先彈出 F2棧幀,再彈出 F1 棧幀,遵循“先進后出”原則。

          No.3 堆

          Heap(堆)是JVM的內(nèi)存數(shù)據(jù)區(qū)。該區(qū)域是被所有線程共享的內(nèi)存區(qū)域,在JVM啟動時候創(chuàng)建,專門用來保存對象的實例。
          在Heap中分配一定的內(nèi)存來保存對象實例,實際上也只是保存對象實例的屬性值,屬性的類型和對象本身的類型標記等,并不保存對象的方法(以幀棧的形式保存在Stack中
          )。而對象實例在Heap中分配好以后,需要在Stack中保存一個4字節(jié)的Heap內(nèi)存地址,用來定位該對象實例在Heap中的位置,便于找到該對象實例。
          堆是線程共享的內(nèi)存區(qū)域,在JVM啟動時候創(chuàng)建,專門用來保存對象的實例。 java堆處于物理不連續(xù)的內(nèi)存空間中,只要邏輯上連續(xù)即可。 垃圾回收的主要場所。

          No.4 方法區(qū)

          方法區(qū)存放了:

          * 加載類的類定義數(shù)據(jù)
          * 常量和靜態(tài)變量
          * JIT(即時編譯器)編譯后的代碼
          方法區(qū)也可以是內(nèi)存不連續(xù)的區(qū)域組成的,并且可設置為固定大小,也可以設置為可擴展的
          垃圾回收在這個區(qū)域會比較少出現(xiàn),這個區(qū)域內(nèi)存回收的目的主要針對常量池的回收和類的卸載。

          No.5 運行時常量池(Runtime Constant Pool)

          方法區(qū)內(nèi)部有一個非常重要的區(qū)域,叫做運行時常量池(Runtime Constant Pool,簡稱 RCP)。
          在字節(jié)碼文件(Class文件)中,除了有類的版本、字段、方法、接口等相關信息描述外,還有常量池(Constant Pool
          Table)信息,用于存儲編譯器產(chǎn)生的字面量和符號引用。這部分內(nèi)容在類被加載后,都會存儲到方法區(qū)中的RCP。值得注意的是,運行時產(chǎn)生的新常量也可以被放入常量池中,比如
          String 類中的 intern() 方法產(chǎn)生的常量。
          常量池就是這個類型用到的常量的一個有序集合。包括直接常量(基本類型,String)和對其他類型、方法、字段的符號引用.例如:

          * 類和接口的全限定名;
          * 字段的名稱和描述符;
          * 方法和名稱和描述符。
          池中的數(shù)據(jù)和數(shù)組一樣通過索引訪問。由于常量池包含了一個類型所有的對其他類型、方法、字段的符號引用,所以常量池在Java的動態(tài)鏈接中起了核心作用.

          No.6 本地方法棧

          與VM Strack相似,VM Strack為JVM提供執(zhí)行JAVA方法的服務,Native Method Stack則為JVM提供使用native
          方法的服務。

          No.7 直接內(nèi)存區(qū)

          直接內(nèi)存區(qū)并不是JVM 管理的內(nèi)存區(qū)域的一部分,而是其之外的。該區(qū)域也會在 Java 開發(fā)中使用到,并且存在導致內(nèi)存溢出的隱患。如果你對 NIO
          有所了解,可能會知道 NIO 是可以使用 Native Methods 來使用直接內(nèi)存區(qū)的。

          JVM內(nèi)存區(qū)域可以分為線程共享和非線程共享兩部分,線程共享的有堆和方法區(qū),非線程共享的有虛擬機棧,本地方法棧和程序計數(shù)器。

          友情鏈接
          ioDraw流程圖
          API參考文檔
          OK工具箱
          云服務器優(yōu)惠
          阿里云優(yōu)惠券
          騰訊云優(yōu)惠券
          京東云優(yōu)惠券
          站點信息
          問題反饋
          郵箱:[email protected]
          QQ群:637538335
          關注微信

                国产女主播呻吟喷水在线观看 | 亚洲人在线观看 | 黄色网址久久 | 亚洲穿丝袜摆弄女尸av | 大逼色网站 |