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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

jvm堆分代

發布時間:2024/4/13 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jvm堆分代 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
JVM堆結構圖及分代JVM虛擬機: JVM內存分代策略Java虛擬機根據對象存活的周期不同,把堆內存劃分為幾塊,一般分為新生代、老年代和永久帶,永久帶也叫持久帶(對HotSpot虛擬機而言),這就是JVM的內存分代的策略.現在我們看到的java堆,實際劃分的顆粒度會更細,實際上把堆按分代的結構來處理呢,那就引申出一個問題了,為什么要分代,對內存是虛擬機管理的內存中的最大的一塊,也是垃圾回收最頻繁的一塊區域,我們程序所有的對象實例都存放在堆內存中. 給堆內存分代是為了提高對象內存分配和來及回收的效率,你想如果堆是一塊內存,然后在這個堆內存中存所有的對象,而且有些都不一樣,有些是朝生夕死的,有些是永久存活的,有些是中間環節的,你把這些對象全都塞到一個內存里,對于垃圾回收來講,是不是難度大大提升,第二個問題,由于內存存放對象的時候是連續的,以后未來你要挑不同的對象做回收,對內存空間做釋放,也就是你內存當中會產生大量的碎片,產生碎片又會帶來什么影響呢,產生碎片最直接的影響就會內存造成浪費,比如原來這一塊是200K,200K,200K三塊,存了三個對象,然后中間的對象唄回收了,被回收這個對象被釋放了200K,現在我要存一個對象300K存不進去,這個時候只能往后面找有沒有連續的兩個200K,那這個200K就浪費掉了,除非小于200K的對象能new上,否則空間就被閑置了所以這就是產生碎片的原因,如果不分代對于垃圾回收來講就很復雜.分而治之,分代最核心的一個策略,試想一下,如果對內存沒有區域劃分,所有新創建的對象和聲明周期很長的對象放在一起,隨著程序的執行,對內存需要頻繁的進行垃圾收集,而每次回收都要遍歷所有的對象,遍歷這些對象所花費的時間代價是巨大的,會嚴重影響GC的效率,也是就是難度的一部分,這簡直太可怕了.有了內存分代,情況就不同了,新創建的對象會在新生代中生成,經過多次回收仍然存活下來的對象放在老年代中靜態屬性、類信息等放在永久代中,新生代存活的時間短,只需要在新生代頻繁進行GC,老年代中對象生命周期長,內存回收頻率相對較低,永久代由于是最長的了,JMV一般不會對永久代做垃圾回收,雖然說它可以,但是它一般不會這么去做.還可以根據不同年代的特點采用合適的垃圾回收算法,分代收集大大提高了收集效率,這些都是內存分代所帶來的好處,它把原來一大塊的東西,分成了小塊,然后把不同的對象放在不同的塊中,經過重重過濾,新生代里面有一個eden區,這里放的永遠都是剛出生的對象,如果eden區的對象并沒有被回收,或者在一定的時間內沒有被回收,這個對象的聲明周期很長,那么就不能放在eden區了,要放到老年代里,然后再是持久代,新生代和持久代仿佛就是一個漏斗在層層過濾,能夠跑到過濾最終點的,一定是這個對象聲明周期最長的,才會到持久代,所以他采用這樣一個方式來解決問題,這是一個很好的方式.內存分代劃分:Java虛擬機將堆內存劃分為新生代,老年代,持久代,永久帶是HotSpot虛擬機所特有的概念,如果你采用的是JDK1.4之前的,不是這個核心的,那就沒有永久代這么一說,它采用永久代的方式來實現方法區,其它的虛擬機實現沒有這一概念,而且HotSpot也有取消永久代的趨勢,在JDK1.7 HotSpot已經開始去永久代,把原本放在永久代的字符串常量池移出,永久代主要存放常量,類信息,靜態變量數據,你有沒有發現堆里面的永久代存放的東西和方法區存放的東西相似,都是生命周期比較長的,可以把這些內容放到方法區里面去存儲,可以節省一塊內存空間

這個圖是顆粒度非常細的java堆的演示,僅是堆的進一步細化的演示,其實我們的堆可以分成5塊區域,JVM會把它分成5塊區域, Eden,from,to這三塊被稱之為年輕代,old老年代,permanent被稱為持久代也有把old和permanent這兩塊放在一起的,在年輕代里又分成三塊,from,to這兩塊的叫法有好多,統稱為Survivor幸存者,對于from有的人叫做survivor0,有的叫s0,有的叫s1,為什么要用0,因為程序查數是從0開始的,也有叫from,to的,這三塊共同構成了年輕代,前面的eden伊甸園,為什么要用這個來命名呢,說明所有對象的出生都是在這個區域里的,他是嬰兒的搖籃,大部分對象的初始化都是在這里,有的對象運行完了就沒事了,在這個橫向劃分當中,Eden的垃圾回收頻率是最高的,而且在Eden區里基本能夠回收到整個對象的百分之80以上,甚至百分之85的對象,都會在Eden里運行完就回收掉了,唯獨剩余的一部分怎么辦呢,他也不會放在Eden里,它會放到Survivor Space,再進一步決定是不是要回收,如果他又沒有被回收掉,然后再把它放在old區.我們在講來垃圾回收器的時候,由于不同的區域回收的頻率不一樣,那么所采用的收集器也是不一樣的,收集器不僅僅是對堆這一塊做回收,它會細化到什么程度呢,對堆里不同的區域做回收,那么也就是說在這個區域里邊,從Survivor之后一分為二,左邊的一個垃圾回收器,右邊的一個垃圾回收器,即便是你不指定,JVM也是這么做的,他不是一個垃圾回收器,而是對不同的堆用不同的垃圾回收器,根據你的區域,根據你的分代,這個叫分代垃圾收集,是不是Eden有一個垃圾回收,是不是from有一個垃圾回收,不是這樣的,它的垃圾回收顆粒度沒有這么細,因為它覺得沒有必要,他就是從中間帶和老年代作為一個中間軸,來采用兩代的垃圾回收新生代(Young Generation):新生成的對象優先存放在新生代中,新生代對象朝生夕死,存活率很低,在新生代中,常規應用一次垃圾收集,一般可以回收70% ~ 90% 的空間,回收率很高.HotSpot將新生代分為三代,一塊較大的Eden空間和兩塊較小的Survivor空間,默認比例是8:1:1,8是80%是Eden,剩下的10%,10%是Survivor區,為什么要給Eden區放這么大的空間,而給Survivor放這么小呢, 因為你想啊,因為大部分的空間都被回收掉了,剩下的就一小部分了,分那么大的空間會造成很大的浪費,沒必要,所以java虛擬機所劃分的區域是8:1:1, HotSpot采用復制算法來回收新生代,什么叫復制算法,設置這個比例是為了充分利用內存空間,減少浪費,新生成的對象在Eden區分配,大對象除外,大對象直接進入老年代,Eden區會放大部分的對象,并不是全部的,另一部分就是大對象,當Eden區沒有足夠空間進行分配時,虛擬機將會發起一次Minor GC, 它的收集器分為兩種, 一種是次收集器,一種是全收集器,其實又叫Minor GC的,Minor GC就是去收集Eden里的一些收集器,就是指收集年輕代的收集器, GC開始時,對象只會存在于Eden區和From Survivor區,to Survivor 區, GC進行時, Eden區中所有存活的對象都會被復制到 to Survivor區, 而在from Survivor區中, 仍存活的對象會根據他們的年齡值決定去向, 年齡值達到年齡閥值(默認是15次),就是被回收15次還沒有被回收掉,新生代中的對象每熬過一輪垃圾回收,當年齡增加1的時候,如果年齡值達到15了,放心不會被回收了,而是放在老年代當中了, 沒有達到閥值的對象會被復制到to Survivor區. 接著清空Eden區和From Survivor區,新生代中存活的對象都在to Survivor區. 接著from Survivor和to Survivor區會交換它們的角色,其實這就是我們要講的復制算法的事件. 其實很好理解,如果年齡沒有超過15次,還在這里放著,內存空間肯定是連續的,通過Minor GC次回收器的回收,超過15次的肯定不會被回收,那怎么辦呢,他不能就把它放在這里呢,放在這里第一個還是會產生碎片,復制算法非常好理解,他會把這些沒有被回收的對象直接拷貝到to Survivor區,并且按照連續的來存儲,然后把from區全都清空,這個時候既保證了空間的釋放,也保證了空間的連續,這就是復制算法,to Survivor里的也不是永久存放,也是通過一個閥值,如果也是比如15次垃圾回收后存活,那就放在old區老年代,然后再把to Survivor區清空,老年代old區是為了給survivor區做一個擔保,就像我們去銀行貸款一樣,old區老年代其實就是給新生代做一個擔保,總之,不管怎樣都會保證to Survivor區在一輪GC后都是空的, GC時當to Survivor區沒有足夠的空間存放上一次新生代收集下來的存活對象時,需要老年代進行分配擔保,將這些對象存放在老年代中.新生代就是用來折騰這戲對象,誰能進入到老年代里.老年代(old generation):在新生代中經歷了多次,具體要看虛擬機配置的閥值,GC后仍然存活下來的對象會進入老年代中. 老年代中的對象生命周期較長,存活率較高,在老年代中進行GC的頻率相對而言較低,而且回收的速度也比較慢.老年代的垃圾回收機制,肯定不會像新生代那么頻繁,因為老年代生命周期較長,還頻繁收集,第一是無用,第二降低虛擬機的性能,沒有必要做高頻的垃圾回收.永久代(Permanent Generation):永久代存儲類信息,常量,靜態變量,即時編譯器編譯后的代碼等數據,對這一區域而言,Java虛擬機規范指出可以不進行垃圾收集,一般而言不會進行垃圾回收.JDK1.8和1.9里已經沒有永久代了,最多就是到老年代了.

?

總結

以上是生活随笔為你收集整理的jvm堆分代的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。