Java后端開發(fā)三年,你不得不了解的JVM-創(chuàng)新互聯(lián)

JAVA程序員,三年是個(gè)坎,如果過(guò)了三年你還沒有去研究JVM的話,那么你這個(gè)程序員只能是板磚的工具了。下面來(lái)個(gè)JVM的解析可好?

網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)!專注于網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、小程序開發(fā)、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了睢寧縣免費(fèi)建站歡迎大家使用!

JVM是Java Virtual Machine(Java虛擬機(jī))的縮寫,也就是指的JVM虛擬機(jī),屬于是一種虛構(gòu)出來(lái)的計(jì)算機(jī),在我們實(shí)際的電腦上來(lái)進(jìn)行模擬各種計(jì)算機(jī)的功能的這么個(gè)東西。

因?yàn)橛辛薐VM的存在,搞JAVA的不再需要去關(guān)心什么時(shí)候去釋放內(nèi)存,也不會(huì)像C++程序員那樣為了一點(diǎn)點(diǎn)內(nèi)存而惆悵,對(duì)就是你,JVM虛擬機(jī)幫你把這些東西都完成了,那么我們來(lái)說(shuō)說(shuō)JAVA的JVM吧!

我們先來(lái)看看JVM的模型吧,之前在百度上看文檔,上面就說(shuō)了幾個(gè),方法區(qū),堆,棧,計(jì)數(shù)器。沒了,很難受,于是看了深入理解JVM的書,也算是有點(diǎn)體會(huì)。

在深入理解JVM一書中提到,JVM運(yùn)行時(shí)的數(shù)據(jù)區(qū)域會(huì)劃分為幾個(gè)不同的區(qū)域,有方法區(qū)(Method Area),虛擬機(jī)棧(VM Stack),本地方法棧(Native Method Stack),堆(heap),程序計(jì)數(shù)器(Program Counter Register),下面就是書中的圖:

Java后端開發(fā)三年,你不得不了解的JVM

咱們一個(gè)一個(gè)來(lái)解釋: 先說(shuō)程序計(jì)數(shù)器(Program Counter Register):程序計(jì)數(shù)器實(shí)際上就是用于存放下一條指令所在地址的地方,當(dāng)我們執(zhí)行一條指令的時(shí)候,要先知道他存放的指令位置,然后把指令帶到寄存器上這是就是獲取指令,然后程序計(jì)數(shù)器中的存貯地址會(huì)加1,然后這樣子循環(huán)的去執(zhí)行,而且程序計(jì)數(shù)器這個(gè)小的內(nèi)存區(qū)是“線程私有的內(nèi)存”。

為什么會(huì)是私有的呢?,在深入理解JVM一書中說(shuō)的是虛擬機(jī)的多線程通過(guò)線程的輪流切換來(lái)切換分配處理器的執(zhí)行時(shí)間的方式來(lái)實(shí)現(xiàn),說(shuō)起來(lái)其實(shí)很拗口的,其實(shí)也就是說(shuō)一個(gè)處理器,同一個(gè)時(shí)刻,只會(huì)執(zhí)行一個(gè)線程的指令,但是時(shí)間可能不均衡,可能第一分鐘在a線程,第二分鐘就去執(zhí)行b線程了,但是呢,為了保證切換回來(lái)還需要是一致的,那么每個(gè)線程中就會(huì)有一個(gè)獨(dú)立存在的程序計(jì)數(shù)器,獨(dú)立來(lái)存貯,為了保證不影響。所以他是一個(gè)“線程私有的內(nèi)存”。

程序計(jì)數(shù)器還有幾個(gè)特點(diǎn):

  • 如果線程正在執(zhí)行的是Java 方法,則這個(gè)計(jì)數(shù)器記錄的是正在執(zhí)行的虛擬機(jī)字節(jié)碼指令地址。

  • 如果正在執(zhí)行的是Native 方法,則這個(gè)計(jì)數(shù)器值為空(Undefined)。

  • 此內(nèi)存區(qū)域是唯一一個(gè)在Java虛擬機(jī)規(guī)范中沒有規(guī)定任何OutOfMemoryError情況的區(qū)域。

分別解釋一下這三句話吧,這是深入理解java虛擬機(jī)中的原話,第一句好像已經(jīng)很直白了,沒的說(shuō),來(lái)說(shuō)說(shuō)第二句話吧

因?yàn)檫@個(gè)計(jì)數(shù)器記錄的是字節(jié)碼指令地址,但是Native(本地方法);就比如說(shuō)(System.currentTimeMillis())他是通過(guò)C來(lái)實(shí)現(xiàn),直接通過(guò)系統(tǒng)就能直接調(diào)用了不需要去編譯成需要執(zhí)行的字節(jié)碼指令的話,那么就相當(dāng)于不過(guò)程序計(jì)數(shù)器,它沒有記錄的話,那他的計(jì)數(shù)器的值就肯定為空了。

第三句話 我們可以試試編譯一小段代碼,然后反編譯出來(lái)看看

Java后端開發(fā)三年,你不得不了解的JVM

也就是實(shí)際上是這個(gè)樣子的

public class Test{ public int test(){ int a = 10; //0 ...... int b = 20; //3....... int c = 30; //6...... return (a+b)*c; //11.... 13.... 14...執(zhí)行加減乘除操作 } }

上面的0,2,3,5,6,8....就是指令的偏移地址bipush就是入棧指令, 在執(zhí)行到test方法的時(shí)候,線程就會(huì)創(chuàng)建對(duì)應(yīng)的程序計(jì)數(shù)器在計(jì)數(shù)器中放0,2,3,5,6,8....這些指令地址,所以計(jì)數(shù)器里改變的不是內(nèi)存的大小,它也就沒有溢出了。

下面我們?cè)賮?lái)說(shuō)一下:JAVA虛擬機(jī)棧(VM Stack)

線程私有,生命周期和線程一樣,這個(gè)虛擬機(jī)棧描述的是JAVA方法執(zhí)行的內(nèi)存模型,用于存局部變量,操作數(shù)棧,方法出口等信息的,上面那個(gè)bipush就是入棧指令,在這里最需要注意的就是他存放的是什么數(shù)據(jù).局部變量里面放的就是那些我們所知道的基本的數(shù)據(jù)類型,對(duì)象引用的話那就是一個(gè)地址。

在虛擬機(jī)規(guī)范里面還說(shuō),他的2個(gè)異常狀況:

  • 一個(gè)是StackOverflowError異常,棧內(nèi)存溢出,這肯定很容易理解,就是棧的內(nèi)存不夠,你的請(qǐng)求線程太大。(固定長(zhǎng)度的棧)

  • 如果說(shuō)在動(dòng)態(tài)擴(kuò)展的過(guò)程中,申請(qǐng)的長(zhǎng)度還是不夠,那么會(huì)拋出另外一個(gè)異常OutOfMemoryError異常。

本地方法棧(Native Method Stack) :

它和虛擬機(jī)棧很類似,區(qū)別就在于虛擬機(jī)棧執(zhí)行的是JAVA方法,但是本地方法棧則是Native方法,其他的沒啥不同就連拋出異常都一樣的。

JAVA堆(heap)?在JVM一書中也有提到,Heap是在JAVA虛擬機(jī)中內(nèi)存占用大的一個(gè)地方,也是所有線程共享的一個(gè)內(nèi)存區(qū)域,堆內(nèi)存中主要就是用于存放對(duì)象實(shí)例的。

幾乎是所有的對(duì)象實(shí)例都在這里分配內(nèi)存,JAVA堆是垃圾收集器管理的主要區(qū)域,那么現(xiàn)在重點(diǎn)來(lái)了,面試中問到最多的垃圾回收機(jī)制接下來(lái)就要仔細(xì)說(shuō)說(shuō)了。

內(nèi)存回收,現(xiàn)在都是進(jìn)行的分代算法,堆中也是,新生代,老年代,而且兩種垃圾回收機(jī)制是采用的不同的回收機(jī)制的,在新生代中,每次垃圾收集時(shí)都發(fā)現(xiàn)有大批對(duì)象死去,只有少量存活,那就選用復(fù)制算法,只需要付出少量存活對(duì)象的復(fù)制成本就可以完成收集。

而老年代中因?yàn)閷?duì)象存活率高、沒有額外空間對(duì)它進(jìn)行分配擔(dān)保,就必須使用"標(biāo)記-清理"或"標(biāo)記-壓縮"算法來(lái)進(jìn)行回收,說(shuō)回收機(jī)制先看看heap的分區(qū)(這個(gè)from和to 并不是絕對(duì)的,看對(duì)象處在哪個(gè)位置,GC的次數(shù)不一樣之后,那from和to會(huì)有相應(yīng)轉(zhuǎn)變)

Java后端開發(fā)三年,你不得不了解的JVM

分區(qū)一目了然,下面研究一下算法實(shí)現(xiàn)吧

Minor GC:GC新生代,

Full GC:老年代GC,

因?yàn)樾律袑?duì)象的存活率比較低,所以一般采用復(fù)制算法,老年代的存活率一般比較高,一般使用”標(biāo)記-清理”或者”標(biāo)記-整理”算法進(jìn)行回收。

看了有幾天才明白啥意思,我說(shuō)說(shuō)我自己的見解吧,還是畫圖吧,

Minor GC:

我們每次new對(duì)象的時(shí)候都會(huì)先在新生代的Enden區(qū)放著也就是最開始 是這樣子的

Java后端開發(fā)三年,你不得不了解的JVM

然后在Enden用完的時(shí)候里面會(huì)出現(xiàn)待回收的

Java后端開發(fā)三年,你不得不了解的JVM

然后就來(lái)了把存活的對(duì)象復(fù)制放到Survior1(from)中,待回收的等待給他回收掉 就是這樣的

Java后端開發(fā)三年,你不得不了解的JVM

然后把Enden區(qū)清空回收掉

Java后端開發(fā)三年,你不得不了解的JVM

這樣的話 第一次GC就完成了,下面再往下走

當(dāng)Enden充滿的時(shí)候就會(huì)再次GC

先是這個(gè)樣子的

Java后端開發(fā)三年,你不得不了解的JVM

然后會(huì)把 Enden和Survoir1中的內(nèi)容復(fù)制到Survior中,

Java后端開發(fā)三年,你不得不了解的JVM

然后就會(huì)把Enden和Survior進(jìn)行回收

Java后端開發(fā)三年,你不得不了解的JVM

然后從Enden中過(guò)去的就相當(dāng)于次數(shù)少的,而從Survior1中過(guò)去的就相當(dāng)于移動(dòng)了2次

Java后端開發(fā)三年,你不得不了解的JVM

這樣新生代的GC就執(zhí)行了2次了,

當(dāng)Enden再次被使用完成的時(shí)候,就會(huì)從Survior2復(fù)制到Survior1中,

接下來(lái)是連圖

Java后端開發(fā)三年,你不得不了解的JVM

經(jīng)過(guò)回收之后Surior1就變了,1對(duì)象是從Enden直接復(fù)制過(guò)來(lái)的,2對(duì)象是Enden-->Survior2-->Survior1 ,3對(duì)象則是從Enden-->Surivior1-->Survior2-->Survior1 復(fù)制過(guò)來(lái)的,這樣一步一步的執(zhí)行下去的時(shí)候,就是新生代的GC。

既然這樣,那為什么還會(huì)存在老年代呢?其實(shí)如果GC在執(zhí)行的時(shí)候有些對(duì)象一直沒有被回收,那么他移動(dòng)次數(shù)就會(huì)無(wú)限的累計(jì),每次從Surior(from)到Surior(to)的過(guò)程中就相當(dāng)于又增加了一次移動(dòng),當(dāng)他達(dá)到一定的次數(shù)的時(shí)候(默認(rèn)是15),就會(huì)移動(dòng)到老年代里了,所以不存在不會(huì)被回收的對(duì)象,但是這個(gè)次數(shù)可以設(shè)置的,

-XX:MaxTenuringThreshold

就類似這樣子

Java后端開發(fā)三年,你不得不了解的JVM

其實(shí)上邊的這只是一種情況,還有就是如果對(duì)象太大,存不下,那就直接會(huì)進(jìn)入老年代。

還有那種默認(rèn)就是長(zhǎng)期活著的也會(huì)進(jìn)入老年代,

而且這種復(fù)制算法的垃圾回收機(jī)制是比較浪費(fèi)內(nèi)存的,每次都會(huì)有一塊內(nèi)存區(qū)是閑著不干活的,但是優(yōu)點(diǎn)很明顯,簡(jiǎn)單高效

以上就是GC中垃圾回收中的新生代復(fù)制算法解析,新生代的Minor GC也算是知道了不少東西了,以上就是一些個(gè)人的見解,圖比較清晰,容易理解,有不對(duì)的地方希望能夠各位同行指點(diǎn)一下。

看到這里了點(diǎn)個(gè)贊再走唄

順便給大家推薦一個(gè)Java技術(shù)交流群:908676731,里面會(huì)分享一些資深架構(gòu)師錄制的視頻資料:有Spring,MyBatis,Netty源碼分析,高并發(fā)、高性能、分布式、微服務(wù)架構(gòu)的原理,JVM性能優(yōu)化、分布式架構(gòu)等這些成為架構(gòu)師必備的知識(shí)體系。還能領(lǐng)取免費(fèi)的學(xué)習(xí)資源,目前受益良多!

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。

網(wǎng)站名稱:Java后端開發(fā)三年,你不得不了解的JVM-創(chuàng)新互聯(lián)
文章出自:http://bm7419.com/article46/dehheg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)建站建站公司、搜索引擎優(yōu)化、響應(yīng)式網(wǎng)站、網(wǎng)站維護(hù)、網(wǎng)站營(yíng)銷

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

小程序開發(fā)