1. JVM 運(yùn)行時(shí)數(shù)據(jù)區(qū)詳解,寫(xiě)得非常好!

        共 2861字,需瀏覽 6分鐘

         ·

        2020-07-27 19:19

        Java技術(shù)棧

        www.javastack.cn

        關(guān)注閱讀更多優(yōu)質(zhì)文章



        作者:小小木的博客
        www.cnblogs.com/wyc1994666/p/11795781.html


        在接下來(lái)的幾天想總結(jié)下,JVM相關(guān)的一些內(nèi)容,比如下面的這三個(gè)內(nèi)容算是比較核心知識(shí)點(diǎn)了

        1.運(yùn)行時(shí)數(shù)據(jù)區(qū)域: 在運(yùn)行時(shí)數(shù)據(jù)區(qū)里存儲(chǔ)類Class文件元數(shù)據(jù)(方法區(qū)),對(duì)象和數(shù)組(堆),方法參數(shù)局部變量(棧)等。

        2.垃圾回收機(jī)制: java 語(yǔ)言的優(yōu)勢(shì)之一就是它的自動(dòng)內(nèi)存管理,主要回收運(yùn)行時(shí)數(shù)據(jù)區(qū)域的堆內(nèi)存里的數(shù)據(jù)

        3.類加載機(jī)制: 虛擬機(jī)首先需要把編譯完成的字節(jié)碼文件通過(guò)類加載器來(lái)加載到運(yùn)行時(shí)數(shù)據(jù)區(qū)域

        一個(gè)段Java代碼的生命周期都會(huì)少不了上圖這幾個(gè)步驟,也就是Java代碼首先會(huì)被編譯成字節(jié)碼文件,之后被類加載器加載到運(yùn)行時(shí)數(shù)據(jù)區(qū)域,以及運(yùn)行,垃圾收集器回收對(duì)象等等。

        但今天我想介紹第一個(gè)知識(shí)點(diǎn)《運(yùn)行時(shí)數(shù)據(jù)區(qū)域》

        1 運(yùn)行時(shí)數(shù)據(jù)區(qū)

        Java虛擬機(jī)定義了一系列邏輯數(shù)據(jù)區(qū)域,有些是隨著虛擬機(jī)的啟動(dòng)而創(chuàng)建,虛擬機(jī)的關(guān)閉而銷毀。還有一部分是隨著線程生命周期創(chuàng)建銷毀的。

        我們有必要深入了解這塊的內(nèi)容,因?yàn)樗鼘Q定服務(wù)器性能,首先我們需要對(duì)整個(gè)運(yùn)行時(shí)區(qū)域由整體的認(rèn)識(shí)并且了解了每個(gè)區(qū)域的生命周期以及作用之后才能通過(guò)相應(yīng)的調(diào)參來(lái)提升系統(tǒng)性能。除此之外還有助于快速定位虛擬機(jī)的相關(guān)Error.

        邏輯上可以劃出一下6個(gè)區(qū)域分別是

        1.1 PC寄存器

        全名叫做 Program Counter Register 既然是叫做寄存器了那么肯定是需要存東西,那到底存的是什呢?

        由于JVM同時(shí)可以處理多個(gè)線程所以就涉及到一些線程調(diào)度,當(dāng)cpu暫停運(yùn)行線程A把時(shí)間片讓給線程B的時(shí)候我們需要保存線程A被暫停執(zhí)行前的一些現(xiàn)場(chǎng)狀態(tài),需要記錄當(dāng)前執(zhí)行到那一行字節(jié)碼了,所以具備保存現(xiàn)場(chǎng)的功能。

        每條線程都有自己的pc寄存器,在任意時(shí)刻虛擬機(jī)只會(huì)執(zhí)行一個(gè)方法,如果執(zhí)行的是方法不是native方法 pc寄存器則保存指向當(dāng)前執(zhí)行字節(jié)碼的指令地址,如果執(zhí)行的是native方法 pc寄存器會(huì)保存undefined。

        1.2 java虛擬機(jī)棧

        虛擬機(jī)棧也是每條線程私有的區(qū)域,里頭存儲(chǔ)棧幀(Frame),后面會(huì)重點(diǎn)介紹棧幀算是重點(diǎn)內(nèi)容。方法的調(diào)用與返回基于棧幀來(lái)實(shí)現(xiàn)的。

        1.3 虛擬機(jī)堆

        在Java虛擬機(jī)中堆是所有線程都可以共享的內(nèi)存區(qū)域,是存放所有類實(shí)例和數(shù)組對(duì)象的地方。在虛擬機(jī)啟動(dòng)就根據(jù)相關(guān)堆參數(shù),創(chuàng)建堆,他也是垃圾收集器工作的主要區(qū)域。

        堆內(nèi)存里的對(duì)象不會(huì)被顯式的回收,而是由垃圾回收器回收,為了配合垃圾收集器的特性我們可以把堆分為年輕代和老年代。

        年輕代又分了Eden和survivor區(qū),主要是為了配合垃圾回收算法而這么搞得。

        1.4 方法區(qū)和運(yùn)行時(shí)常量池

        在Java虛擬機(jī)中 方法區(qū)是可提供各個(gè)線程共享的運(yùn)行時(shí)內(nèi)存區(qū)域,它存儲(chǔ)了每一個(gè)類的結(jié)構(gòu)信息,例如運(yùn)行時(shí)常量池,字段和方法數(shù)據(jù),構(gòu)造函數(shù)和普通函數(shù)的字節(jié)碼內(nèi)容,一句話總結(jié)就是存儲(chǔ)元數(shù)據(jù)地方

        運(yùn)行時(shí)常量池是class文件中每個(gè)類或接口常量池表的表示形式。它包括了若干不同的常量,比如 從編譯期可知的數(shù)值字面量到運(yùn)行時(shí)才能解析獲得的方法或字段引用等等。

        創(chuàng)建時(shí)機(jī)

        每個(gè)運(yùn)行時(shí)常量池都在Java虛擬機(jī)的方法區(qū)中分配,在加載類和接口到虛擬機(jī)之后創(chuàng)建對(duì)應(yīng)的運(yùn)行時(shí)常量池

        1.5 本地方法棧

        如果我們想再Java底層里調(diào)用別的語(yǔ)言代碼的話就需要用到別的方法棧了,比如Java虛擬機(jī)的實(shí)現(xiàn)會(huì)用到傳統(tǒng)的棧(C stack)來(lái)調(diào)用native方法,這個(gè)就是本地方法棧的應(yīng)用,當(dāng)然這個(gè)不是必須實(shí)現(xiàn)的,完全取決于虛擬機(jī)的實(shí)現(xiàn)。

        2 棧幀:

        首先看下棧幀在虛擬機(jī)內(nèi)存中在什么位置,

        棧幀是用來(lái)存儲(chǔ)數(shù)據(jù)和部分過(guò)程結(jié)果的數(shù)據(jù)結(jié)構(gòu),同時(shí)也用來(lái)處理動(dòng)態(tài)鏈接,方法返回,異常分派等工作。

        棧幀的生命周期是跟方法一致的,隨著方法的調(diào)用而創(chuàng)建,方法的結(jié)束或者異常而銷毀。

        每個(gè)棧幀都由局部變量表,操作數(shù)棧,動(dòng)態(tài)鏈接組成的

        2.1 局部變量表 (Local variable)

        每個(gè)棧幀內(nèi)部都包含一組稱為局部變量表的列表,變量表的長(zhǎng)度在編譯期決定。另外關(guān)注公眾號(hào)Java技術(shù)棧在后臺(tái)回復(fù)JVM獲取一份46頁(yè)的JVM調(diào)優(yōu)教程。

        一個(gè)局部變量可以存儲(chǔ)一個(gè)基本數(shù)據(jù)類型或一個(gè)對(duì)象引用(referance),returnAddress的數(shù)據(jù)。存儲(chǔ)long或double需要兩個(gè)局部變量才能存儲(chǔ)。

        當(dāng)虛擬機(jī)要使用局部變量表里的數(shù)據(jù)時(shí)通過(guò)索引來(lái)定位,默認(rèn)從0開(kāi)始,由于long和double占用兩個(gè)局部變量所以它的索引較特殊,取決于最小的那個(gè)值,比如某個(gè)long類型數(shù)據(jù)在索引n和n+1里存儲(chǔ)了,那么它對(duì)應(yīng)的索引值就是n.
        虛擬機(jī)通過(guò)局部變量表來(lái)完成方法調(diào)用時(shí)的參數(shù)傳遞。如果是類方法,它的參數(shù)依次從0開(kāi)始的位置傳遞到局部變量表,如果是實(shí)例方法則第0位置存儲(chǔ)所在對(duì)象的引用(this),從1開(kāi)始傳遞參數(shù)。

        2.2 操作數(shù)棧 (Operating Stack)

        操作數(shù)棧是屬于棧幀中的棧,其實(shí)它的全名叫做當(dāng)前棧幀的初操作數(shù)棧。棧,棧幀,操作數(shù)棧的關(guān)系需要梳理清楚:

        • 棧:是虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)的一個(gè)邏輯區(qū)域,里面存儲(chǔ)了一個(gè)個(gè)棧幀。

        • 棧幀:棧幀代表一個(gè)方法的整個(gè)生命周期,里頭存儲(chǔ)了局部變量表,操作數(shù)棧,動(dòng)態(tài)鏈接

        • 操作數(shù)棧: 剛剛創(chuàng)建時(shí)操作數(shù)棧是空的。虛擬機(jī)提供一些指令從局部變量表把一些常量或者變量值加載到操作數(shù)棧,也提供了從操作數(shù)棧取走數(shù)據(jù)的指令。
          調(diào)用方法時(shí)操作數(shù)棧用來(lái)準(zhǔn)備調(diào)用方法參數(shù)以及接受方法的返回結(jié)果。

        2.3 動(dòng)態(tài)鏈接 (Dynamic Linking)。

        動(dòng)態(tài)鏈接是用來(lái)完成運(yùn)行時(shí)綁定操作的。在棧幀中有一個(gè)指向常量池的當(dāng)前類的一個(gè)引用。在class文件里一個(gè)方法要是調(diào)用其他方法或者方法其他成員變量,則需要通過(guò)符號(hào)引用來(lái)表示。

        • 動(dòng)態(tài)鏈接的作用就是將符號(hào)引用轉(zhuǎn)換為直接引用。

        • 類加載的過(guò)程中將要解析尚未被解析的符號(hào)引用,并且把對(duì)變量的訪問(wèn)轉(zhuǎn)換為正確的偏移量。

        最近熱文:
        1、盤點(diǎn) 6 個(gè)被淘汰的 Java 技術(shù),曾經(jīng)風(fēng)光過(guò)!
        2、Spring Boot 如何快速集成 Redis?
        3、Spring Boot Redis 實(shí)現(xiàn)分布式鎖,真香!
        4、Mybatis 框架 SQL 注入攻擊的 3 種方式!
        5、Java 14 祭出神器,Lombok 被干掉了?
        6、Java 14 祭出增強(qiáng)版 switch,真香?。?/a>
        7、Spring Boot 2.3 優(yōu)雅關(guān)閉新姿勢(shì),真香!
        8、Spring Boot 干掉了 Maven 擁抱 Gradle!
        9、公司來(lái)了個(gè)新同事不會(huì)用 Lombok!
        10、Spring Cloud 2020 版本重大變革!
        掃碼關(guān)注Java技術(shù)棧公眾號(hào)閱讀更多干貨。

        點(diǎn)擊「閱讀原文」獲取面試題大全~

        瀏覽 48
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
          
          

            1. 掀开裙子从后面猛地挺进公交车里 | 我被室友们强了h女百合gl | 欧美色视频网站 | 免费看黄视频在线观看 | 午夜抽插 |