麻豆黑色丝袜jk制服福利网站-麻豆精品传媒视频观看-麻豆精品传媒一二三区在线视频-麻豆精选传媒4区2021-在线视频99-在线视频a

千鋒教育-做有情懷、有良心、有品質(zhì)的職業(yè)教育機(jī)構(gòu)

手機(jī)站
千鋒教育

千鋒學(xué)習(xí)站 | 隨時(shí)隨地免費(fèi)學(xué)

千鋒教育

掃一掃進(jìn)入千鋒手機(jī)站

領(lǐng)取全套視頻
千鋒教育

關(guān)注千鋒學(xué)習(xí)站小程序
隨時(shí)隨地免費(fèi)學(xué)習(xí)課程

當(dāng)前位置:首頁  >  技術(shù)干貨  > JVM內(nèi)存分配

JVM內(nèi)存分配

來源:千鋒教育
發(fā)布人:qyf
時(shí)間: 2022-06-07 15:53:00 1654588380

JVM內(nèi)存分配

  這個(gè)題很難回答,你的知識儲備要比較強(qiáng)了,他可擴(kuò)展性太強(qiáng)了,咱們開始講解 :

  JVM內(nèi)存管理分為兩部分:內(nèi)存分配、內(nèi)存回收、內(nèi)存回收經(jīng)常也被叫做垃圾回收。

  很多人迷惑一個(gè)問題,既然Java采用自動(dòng)內(nèi)存管理,程序員不用關(guān)心內(nèi)存管理的細(xì)節(jié),那么為什么我們?nèi)匀恍枰私釰ava內(nèi)存管理的內(nèi)幕?

  1.了解Java內(nèi)存管理的細(xì)節(jié),有助于程序員編寫出性能更好的程序。

  比如,在新的線程創(chuàng)建時(shí),JVM會為每個(gè)線程創(chuàng)建一個(gè)專屬的棧(stack),其棧是先進(jìn)后出的數(shù)據(jù)結(jié)構(gòu),這種方式的特點(diǎn),讓程序員編程時(shí),必須特別注意遞歸方法要盡量少使用,另外棧的大小也有一定的限制,如果過多的遞歸,容易導(dǎo)致stack overflow。

  2.了解Java內(nèi)存管理的細(xì)節(jié),一旦內(nèi)存管理出現(xiàn)問題,有助于找到問題的根本原因所在。

  3.了解Java內(nèi)存管理的內(nèi)幕,有助于優(yōu)化JVM,使自己的應(yīng)用獲得最好性能體驗(yàn)。

  內(nèi)存---Java中哪些組件用到內(nèi)存---內(nèi)存分配機(jī)制---內(nèi)存回收機(jī)制

  內(nèi)存:物理內(nèi)存和虛擬內(nèi)存,物理內(nèi)存就是常說的RAM(隨機(jī)存儲器),操作系統(tǒng)作為我們管理計(jì)算機(jī)物理內(nèi)存的接口,我們通常都是通過調(diào)用計(jì)算機(jī)操作系統(tǒng)來訪問內(nèi)存的,在Java中,甚至不需要寫和內(nèi)存相關(guān)的代碼。通常操作系統(tǒng)管理內(nèi)存申請空間是按照進(jìn)程來管理的,每個(gè)進(jìn)程都有一段獨(dú)立的空間,互不重合,互不訪問。這里所說的內(nèi)存空間的獨(dú)立是指邏輯上的獨(dú)立,由操作系統(tǒng)來保證的。虛擬內(nèi)存的出現(xiàn)使得多個(gè)進(jìn)程可以同時(shí)運(yùn)行時(shí)共享物理內(nèi)存,空間上共享,邏輯仍然互不訪問。虛擬內(nèi)存提高了內(nèi)存利用率,擴(kuò)展了內(nèi)存地址空間。

  內(nèi)核空間和用戶空間:通常一個(gè)4GB的物理內(nèi)存地址空間并不能完全被使用,因?yàn)樗粍澐譃閮刹糠郑簝?nèi)核空間和用戶空間【內(nèi)核空間】主要是指操作系統(tǒng)運(yùn)行時(shí)用于程序調(diào)度、虛擬內(nèi)存的使用或者連接硬件資源的程序邏輯。【用戶空間】是用戶運(yùn)行程序能夠申請使用的空間。

  為什么這么劃分呢?

  1)有效抵御惡意用戶的窺探,也能防止質(zhì)量低劣的用戶程序的侵害,從而使系統(tǒng)運(yùn)行得更穩(wěn)定可靠。

  2)用戶空間與內(nèi)核空間的權(quán)限不同,內(nèi)核空間擁有所有硬件設(shè)備的權(quán)限,用戶空間只有普通硬件的權(quán)限;兩者隔離可以防止用戶程序直接訪問硬件資源。

  但是,每一次系統(tǒng)調(diào)用都會在兩個(gè)內(nèi)存空間之間切換,通過網(wǎng)絡(luò)傳輸?shù)臄?shù)據(jù)首先被接收到內(nèi)核空間,然后再從內(nèi)核空間復(fù)制到用戶空間供用戶使用。這樣比較費(fèi)時(shí),雖然保證了程序運(yùn)行的安全性和穩(wěn)定性,但同時(shí)也犧牲了一部分效率。(后來出現(xiàn)了一些列優(yōu)化技術(shù),如Linux提供的sendfile文件傳輸方式)

  另外:Windows32位操作系統(tǒng)【內(nèi)核空間:用戶空間=1:1】、Linux32位操作系統(tǒng)【內(nèi)核空間:用戶空間=1:3】

  Java中的內(nèi)存就是從物理內(nèi)存中申請下來的內(nèi)存,它怎么被劃分的呢?

  Java內(nèi)存模型:一個(gè)Java程序的具體執(zhí)行流程如下:

圖片5

  首先Java源代碼文件(.java后綴)會被Java編譯器編譯為字節(jié)碼文件(.class后綴),然后由JVM中的類加載器加載各個(gè)類的字節(jié)碼文件,加載完畢之后,交由JVM執(zhí)行引擎執(zhí)行。在整個(gè)程序執(zhí)行過程中,JVM會用一段空間來存儲程序執(zhí)行期間需要用到的數(shù)據(jù)和相關(guān)信息,這段空間一般被稱作為Runtime Data Area(運(yùn)行時(shí)數(shù)據(jù)區(qū)),也就是我們常說的JVM內(nèi)存。

  我們常說的Java內(nèi)存管理就是指這塊區(qū)域的內(nèi)存分配和回收,那么,這塊兒區(qū)域具體是怎么劃分的呢?

  根據(jù)《Java虛擬機(jī)規(guī)范》的規(guī)定,運(yùn)行時(shí)數(shù)據(jù)區(qū)通常包括這幾個(gè)部分:

  程序計(jì)數(shù)器(ProgramCounter Register)

  Java棧(VM Stack)

  本地方法棧(Native MethodStack)

  方法區(qū)(Method Area)

  堆(Heap)

  Java堆和方法區(qū)是所有線程共享(所有執(zhí)行引擎可訪問);

  【Java堆】用于存儲Java對象,每個(gè)Java對象都是這個(gè)對象類的副本,會復(fù)制包含繼承自它父類的所有非靜態(tài)屬性。

  【方法區(qū)】用于存儲類結(jié)構(gòu)信息,class文件加載進(jìn)JVM時(shí)會被解析成JVM識別的幾個(gè)部分分別存儲在不同的數(shù)據(jù)結(jié)構(gòu)中:常量池、域、方法數(shù)據(jù)、方法體、構(gòu)造函數(shù),包括類中的方法、實(shí)例初始化、接口初始化等。

  方法區(qū)被JVM的GC回收器管理,但是比較穩(wěn)定,并沒有那么頻繁的被GC回收。

  java棧和PC寄存器(程序計(jì)數(shù)器)是線程私有,每個(gè)執(zhí)行引擎啟動(dòng)時(shí)都會創(chuàng)建自己的java棧和PC寄存器;

  【Java棧】和線程關(guān)聯(lián),每個(gè)線程創(chuàng)建的時(shí)候,JVM都會為他分配一個(gè)對應(yīng)的Java棧,這個(gè)棧含有多個(gè)棧幀;棧幀則是個(gè)方法關(guān)聯(lián),每個(gè)方法的運(yùn)行都會創(chuàng)建一個(gè)自己的棧幀,含有內(nèi)存變量,操作棧、方法返回值。(用于存儲方法參數(shù)、局部變量、方法返回值和運(yùn)算中間結(jié)果)

  【PC寄存器】則用于記錄下一條要執(zhí)行的字節(jié)碼指令地址和被中斷地址。如果方法是 native的,程序計(jì)數(shù)器的值不會被定義為空。

  【本地方法棧】是為JVM運(yùn)行Native方法(本地方法:非java語言編寫的方法,被編譯成和處理器相關(guān)的代碼)準(zhǔn)備的空間,類似于Java棧。

  【運(yùn)行時(shí)常量池】關(guān)于這個(gè)東西要明白三個(gè)概念:

  常量池(Constant Pool):常量池?cái)?shù)據(jù)編譯期被確定,是Class文件中的一部分。存儲了類、方法、接口等中的常量,當(dāng)然也包括字符串常量。

  字符串池/字符串常量池(String Pool/String Constant Pool):是常量池中的一部分,存儲編譯期類中產(chǎn)生的字符串類型數(shù)據(jù)。

  運(yùn)行時(shí)常量池(Runtime Constant Pool):方法區(qū)的一部分,所有線程共享。虛擬機(jī)加載Class后把常量池中的數(shù)據(jù)放入到運(yùn)行時(shí)常量池。

  Java中哪些組件用到內(nèi)存

  Java堆:Java堆用于存儲Java對象,在JVM啟動(dòng)時(shí)就一次性申請到固定大小的空間,所以,一旦分配,大小不變。

  內(nèi)存空間管理:JVM

  對象創(chuàng)建:Java應(yīng)用程序

  對象所占空間釋放:垃圾收集器

  線程:JVM運(yùn)行實(shí)際程序的實(shí)體就是線程,每個(gè)線程創(chuàng)建的時(shí)候JVM都為它創(chuàng)建了私有的堆棧和程序計(jì)數(shù)器(或者叫做PC寄存器);很多應(yīng)用程序是根據(jù)CPU的核數(shù)來分配創(chuàng)建的線程數(shù)。

  類和類加載器:Java中的類和類加載器同樣需要存儲空間,被存儲在永久代(PermGen區(qū))當(dāng)中。

  JVM加載類方式:按需加載,只加載那些你在程序中明確使用到的類,通常只加載一次,如果一直重復(fù)加載,可能會導(dǎo)致內(nèi)存泄露,所以也要注意對PernGen區(qū)失效類的卸載內(nèi)存回收問題。

  通常PernGen區(qū)滿足內(nèi)存回收的條件為:

  1) 堆中沒有對該類加載器的引用;(java.lang.ClassLoader對象)

  2) 堆中沒有對類加載器加載的類的引用;(java.lang.Class對象)

  3) 該類加載器加載的類的所有實(shí)例化的對象不再存活。

  NIO:使用java.nio.ByteBuffer.allocateDirect()方法分配內(nèi)存,每次分配內(nèi)存都會調(diào)用操作系統(tǒng)函數(shù)os::malloc(),所以,分配的內(nèi)存是本機(jī)的內(nèi)存而不是Java堆上的內(nèi)存;

  另外利用該方法產(chǎn)生的數(shù)據(jù)和網(wǎng)絡(luò)、磁盤發(fā)生交互的時(shí)候都是在內(nèi)核空間發(fā)生的,不需要復(fù)制到用戶空間Java內(nèi)存中,這種技術(shù)避免了Java堆和本機(jī)堆之間的數(shù)據(jù)復(fù)制;但是利用該方法生成的數(shù)據(jù)會作為Java堆GC的一部分來自動(dòng)清理本機(jī)緩沖區(qū)。

  JNI:技術(shù)使本機(jī)代碼可調(diào)用java代碼,Java代碼的運(yùn)行本身也依賴于JNI代碼來實(shí)現(xiàn)類庫功能,所以JNI也增加內(nèi)存占用。

  JVM內(nèi)存分配與回收:內(nèi)存分配、通常的內(nèi)存分配策略、操作系統(tǒng)中內(nèi)存分配策略通常分為三類:

  【靜態(tài)內(nèi)存分配】編譯時(shí)就分配了固定的內(nèi)存空間(編譯器確定所需空間大小),不允許有可變數(shù)據(jù)和遞歸嵌套等情況,這樣難以計(jì)算具體空間;

  【棧內(nèi)存分配】在程序運(yùn)行時(shí)進(jìn)入一個(gè)程序模塊(程序入口處確定空間大小)知道一個(gè)程序模塊分配所需數(shù)據(jù)區(qū)大小并為之分配內(nèi)存。

  【堆內(nèi)存分配】在程序運(yùn)行到相應(yīng)代碼是才會知道所需空間大小。(運(yùn)行時(shí)確定空間大小)

  很明顯,三種分配策略中,堆內(nèi)存分配策略最自由,但是效率也是比較差的。

  Java內(nèi)存分配: 在Java程序運(yùn)行過程中,JVM定義了各種區(qū)域用于存儲運(yùn)行時(shí)數(shù)據(jù)。其中的有些數(shù)據(jù)區(qū)域在JVM啟動(dòng)時(shí)創(chuàng)建,并只在JVM退出時(shí)銷毀;其它的數(shù)據(jù)區(qū)域與每個(gè)線程相關(guān)。這些數(shù)據(jù)區(qū)域,在線程創(chuàng)建時(shí)創(chuàng)建,在線程退出時(shí)銷毀。

  棧和線程:JVM是基于棧的虛擬機(jī),為每個(gè)新創(chuàng)建的線程都分配一個(gè)棧,也就是說一個(gè)Java程序來說,它的運(yùn)行就是通過對棧的操作來完成的。棧以幀為單位保存線程的狀態(tài)。JVM對棧只進(jìn)行兩種操作:以幀為單位的壓棧和出棧操作。

  某個(gè)線程正在執(zhí)行的方法稱為此線程的當(dāng)前方法,當(dāng)前方法使用的幀稱為當(dāng)前幀。當(dāng)線程激活一個(gè)Java方法,JVM就會在線程的 Java堆棧里新壓入一個(gè)幀。這個(gè)幀自然成為了當(dāng)前幀.在此方法執(zhí)行期間,這個(gè)幀將用來保存參數(shù),局部變量,中間計(jì)算過程和其他數(shù)據(jù)。這個(gè)幀在這里和編譯原理中的活動(dòng)紀(jì)錄的概念是差不多的。

  從Java的這種分配機(jī)制來看,可以這樣理解:棧(Stack)是操作系統(tǒng)在建立某個(gè)進(jìn)程時(shí)或者線程(在支持多線程的操作系統(tǒng)中是線程)為這個(gè)線程建立的存儲區(qū)域,該區(qū)域具有先進(jìn)后出的特性。

  堆和棧的區(qū)別:棧(stack)與堆(heap)都是Java用來在Ram中存放數(shù)據(jù)的地方 。與C++不同,Java自動(dòng)管理?xiàng):投眩绦騿T不能直接地設(shè)置棧或堆。

  棧的優(yōu)勢:是存取速度比堆要快 ,僅次于直接位于CPU中的寄存器,缺點(diǎn)是,存在棧中的數(shù)據(jù)大小與生存期必須是確定的,缺乏靈活性。另外,棧數(shù)據(jù)可 以共享,詳見第4點(diǎn)。

  堆的優(yōu)勢:是可以動(dòng)態(tài)地分配內(nèi)存大小,生存期也不必事先告訴編譯器,Java的垃圾收集器會自動(dòng)收走這些不再使用的數(shù)據(jù)。但缺點(diǎn)是,由于要在運(yùn)行時(shí)動(dòng)態(tài)分配內(nèi)存,存取速度較慢。

  兩者存儲數(shù)據(jù)類型不同:堆是一個(gè)運(yùn)行時(shí)數(shù)據(jù)區(qū),存放通過new、newayyray.anewarray和mulitanewarray等指令建立的對象,無需代碼顯式的釋放;棧中存放一些基本類型的變量數(shù)據(jù)和對象句柄(引用);

  Java中所有對象的存儲空間都是在堆中分配的,但是這個(gè)對象的引用卻是在堆棧中分配;也就是說在建立一個(gè)對象時(shí)從兩個(gè)地方都分配內(nèi)存,在堆中分配的內(nèi)存實(shí)際建立這個(gè)對象,而在堆棧中分配的內(nèi)存只是一個(gè)指向這個(gè)堆對象的指針(引用)。

  JVM內(nèi)存回收:幾個(gè)問題要搞清楚

  問題一:什么叫垃圾回收機(jī)制?

  垃圾回收是一種動(dòng)態(tài)存儲管理技術(shù),它自動(dòng)地釋放不再被程序引用的對象,按照特定的垃圾收集算法來實(shí)現(xiàn)資源自動(dòng)回收的功能。當(dāng)一個(gè)對象不再被引用的時(shí)候,內(nèi)存回收它占領(lǐng)的空間,以便空間被后來的新對象使用,以免造成內(nèi)存泄露。

  問題二:java的垃圾回收有什么特點(diǎn)?

  Java語言不允許程序員直接控制內(nèi)存空間的使用。內(nèi)存空間的分配和回收都是由JRE負(fù)責(zé)在后臺自動(dòng)進(jìn)行的,尤其是無用內(nèi)存空間的回收操作(garbagecollection,也稱垃圾回收),只能由運(yùn)行環(huán)境提供的一個(gè)超級線程進(jìn)行監(jiān)測和控制。

  問題三:垃圾回收器什么時(shí)候會運(yùn)行?

  一般是在CPU空閑或空間不足時(shí)自動(dòng)進(jìn)行垃圾回收,而程序員無法精確控制垃圾回收的時(shí)機(jī)和順序等。

  問題四:什么樣的對象符合垃圾回收條件?

  當(dāng)沒有任何獲得線程能訪問一個(gè)對象時(shí),該對象就符合垃圾回收條件。

  問題五:垃圾回收器是怎樣工作的?

  垃圾回收器如發(fā)現(xiàn)一個(gè)對象不能被任何活線程訪問時(shí),他將認(rèn)為該對象符合刪除條件,就將其加入回收隊(duì)列,但不是立即銷毀對象,何時(shí)銷毀并釋放內(nèi)存是無法預(yù)知的。垃圾回收不能強(qiáng)制執(zhí)行,然而java提供了一些方法(如:System.gc()方法),允許你請求JVM執(zhí)行垃圾回收,而不是要求,虛擬機(jī)會盡其所能滿足請求,但是不能保證JVM從內(nèi)存中刪除所有不用的對象。

  問題六:一個(gè)java程序能夠耗盡內(nèi)存嗎?

  可以。垃圾收集系統(tǒng)嘗試在對象不被使用時(shí)把他們從內(nèi)存中刪除。然而,如果保持太多活動(dòng)對象,系統(tǒng)則可能會耗盡內(nèi)存。垃圾回收器不能保證有足夠的內(nèi)存,只能保證可用內(nèi)存盡可能的得到高效的管理。

  問題七:程序中的數(shù)據(jù)類型不一樣存儲地方也不一樣,原生數(shù)據(jù)類型存儲在java棧中,方法執(zhí)行結(jié)束就會消失;對象類型存儲在Java堆中,可以被共享,不一定隨著方法執(zhí)行結(jié)束而消失。

  問題八:如何檢測垃圾?(垃圾檢測機(jī)制)

  垃圾收集器的兩個(gè)任務(wù):正確檢測出垃圾對象和釋放垃圾對象占用的內(nèi)存空間,而前者是關(guān)鍵所在。

  垃圾收集器有一個(gè)根對象集合,包含的元素:1)方法中局部變量的引用;2)Java操作棧中的對象引用;3)常量池中的對象引用;4)本地方法持有的對象引用;5)類的class對象。

  JVM在垃圾回收的時(shí)候會檢查堆中的所有對象是否會被根對象直接或間接的引用,能夠被根對象到達(dá)的叫做活動(dòng)對象,否則叫做非活動(dòng)對象可以被回收。內(nèi)存回收- gc原理: jvm內(nèi)存回收采用的是基于分代的垃圾收集算法

  Sun的JVM Generational Collecting(垃圾回收)原理是這樣的:把對象分為年青代(Young)、年老代(Tenured)、持久代(Perm),對不同生命周期的對象使用不同的算法。(基于對象生命周期分析)

  【設(shè)計(jì)思路】:把對象按照壽命長短來分組,分為年輕代和年老代,新創(chuàng)建的對象被分在年輕代,如果對象經(jīng)過幾次回收后仍然存活,那么再把這個(gè)對象劃分到年老代。年老代的收集頻度沒有那么頻繁,這樣就減少了每次垃圾收集時(shí)所需要的掃描的對象和數(shù)量,從而提高垃圾回收效率。

  Young(年輕代)

  年輕代分三個(gè)區(qū)。一個(gè)Eden區(qū),兩個(gè)Survivor區(qū)。大部分對象在Eden區(qū)中生成。當(dāng)Eden區(qū)滿時(shí),還存活的對象將被復(fù)制到Survivor區(qū)(兩個(gè)中的一個(gè)),當(dāng)這個(gè)Survivor區(qū)滿時(shí),此區(qū)的存活對象將被復(fù)制到另外一個(gè)Survivor區(qū),當(dāng)這個(gè)Survivor去也滿了的時(shí)候,從第一個(gè)Survivor區(qū)復(fù)制過來的并且此時(shí)還存活的對象,將被復(fù)制年老區(qū)(Tenured,需要注意,Survivor的兩個(gè)區(qū)是對稱的,沒先后關(guān)系,所以同一個(gè)區(qū)中可能同時(shí)存在從Eden和Survivor區(qū)復(fù)制過來的對象,而復(fù)制到年老區(qū)的只有從第一個(gè)Survivor過來的對象,而且,Survivor區(qū)總有一個(gè)是空的。

  Tenured(年老代)

  年老代存放從年輕代存活的對象。一般來說年老代存放的都是生命期較長的對象;如果Tenured區(qū)(old區(qū))也滿了,就會觸發(fā)Full GC回收整個(gè)堆內(nèi)存。

  Perm(持久代)

  用于存放類的Class文件或靜態(tài)文件,如Java類、方法等,垃圾回收是由FullGC觸發(fā)的。持久代對垃圾回收沒有顯著影響,但是有些應(yīng)用可能動(dòng)態(tài)生成或者調(diào)用一些class,例如hibernate等,在這種時(shí)候需要設(shè)置一個(gè)比較大的持久代空間來存放這些運(yùn)行過程中新增的類。持久代大小通過-XX:MaxPermSize=進(jìn)行設(shè)置。

  舉個(gè)例子:當(dāng)在程序中生成對象時(shí),正常對象會在年輕代中分配空間,如果是過大的對象也可能會直接在年老代生成(據(jù)觀測在運(yùn)行某程序時(shí)候每次會生成一個(gè)十兆的空間用收發(fā)消息,這部分內(nèi)存就會直接在年老代分配)。年輕代在空間被分配完的時(shí)候就會發(fā)起內(nèi)存回收,大部分內(nèi)存會被回收,一部分幸存的內(nèi)存會被拷貝至Survivor的from區(qū),經(jīng)過多次回收以后如果from區(qū)內(nèi)存也分配完畢,就會也發(fā)生內(nèi)存回收然后將剩余的對象拷貝至to區(qū)。等到to區(qū)也滿的時(shí)候,就會再次發(fā)生內(nèi)存回收然后把幸存的對象拷貝至年老區(qū)。

  通常我們說的JVM內(nèi)存回收總是在指堆內(nèi)存回收,確實(shí)只有堆中的內(nèi)容是動(dòng)態(tài)申請分配的,所以以上對象的年輕代和年老代都是指的JVM的Heap空間,而持久代則是之前提到的MethodArea,不屬于Heap。

  關(guān)于JVM內(nèi)存管理我們需要注意的幾個(gè)地方:

  1、程序中的無用對象、中間對象置為null,可加快內(nèi)存回收。

  2、對象池技術(shù)如果生成的對象是可重用的對象,只是其中的屬性不同時(shí),可以考慮采用對象池減少對象的生成。如果對象池中有空閑的對象就取出使用,沒有則生成新的對象,提高對象復(fù)用率。

  3、JVM性能調(diào)優(yōu)通過配置JVM的參數(shù)來提高垃圾回收的速度,如果在沒有出現(xiàn)內(nèi)存泄露且上面兩種辦法都不能保證JVM內(nèi)存回收時(shí),可以考慮采用JVM調(diào)優(yōu) 的方式來解決,不過一定要經(jīng)過實(shí)體機(jī)的長期測試,因?yàn)椴煌膮?shù)可能引起不同的效果。如-Xnoclassgc參數(shù)等。

  jvm的垃圾回收算法: Java中,垃圾回收(GC,Garbage Collection)的對象是Java堆和方法區(qū)(即永久區(qū)或持久區(qū))

  垃圾指的是在系統(tǒng)運(yùn)行過程當(dāng)中所產(chǎn)生的一些無用的對象,這些對象占據(jù)著一定的內(nèi)存空間,如果長期不被釋放,可能導(dǎo)致OOM。后臺專門有一個(gè)專門用于垃圾回收的線程來進(jìn)行監(jiān)控、掃描,自動(dòng)將一些無用的內(nèi)存進(jìn)行釋放,這就是垃圾收集的一個(gè)基本思想,目的在于防止由程序猿引入的人為的內(nèi)存泄露。

  現(xiàn)代java虛擬機(jī)常用的垃圾回收算法有三種,分別是標(biāo)記-清除算法、復(fù)制算法、標(biāo)記-整理算法

  標(biāo)記-清除算法

  (1)概念:標(biāo)記-清除算法是現(xiàn)代垃圾回收算法的思想基礎(chǔ)。它將垃圾回收分為兩個(gè)階段:標(biāo)記階段和清除階段。

  標(biāo)記階段:首先,通過根節(jié)點(diǎn),標(biāo)記所有從根節(jié)點(diǎn)開始的可達(dá)對象。未被標(biāo)記的對象就是未被引用的垃圾對象;

  清除階段:然后,清除所有未被標(biāo)記的對象。

  (2)算法詳解原理:當(dāng)堆中的可用有效內(nèi)存空間(available memory)被耗盡的時(shí)候,就暫停整個(gè)程序(也被成為stop the world),然后進(jìn)行標(biāo)記和清除兩項(xiàng)工作,然后讓程序恢復(fù)運(yùn)行。

  標(biāo)記:標(biāo)記的過程其實(shí)就是,遍歷所有的GC Roots,然后將所有GC Roots可達(dá)的對象標(biāo)記為存活的對象。

  清除:清除的過程將遍歷堆中所有的對象,將沒有標(biāo)記的對象全部清除掉。

  疑問:為什么非要停止程序的運(yùn)行呢?

  答:不難理解,假設(shè)程序與GC線程一起運(yùn)行,當(dāng)對象A處于標(biāo)記階段,被標(biāo)記為垃圾對象后,試想此時(shí)新new了一個(gè)對象B,且對象A可達(dá)B。但是由于此時(shí)A對象已經(jīng)標(biāo)記結(jié)束,B對象錯(cuò)過了標(biāo)記階段。因此當(dāng)接下來清除階段會被,新對象B會隨著A被標(biāo)記被清除掉,變?yōu)閚ull,這樣就亂套了。如此一來,要想正常清除垃圾資源,GC線程必須要暫停程序。

  (3)標(biāo)記-清除算法的缺點(diǎn):首先,它的缺點(diǎn)就是效率比較低(遞歸與全堆對象遍歷),暫停程序stop the world的時(shí)間比較長。(尤其對于交互式的應(yīng)用程序來說簡直是無法接受。試想一下,如果你玩一個(gè)網(wǎng)站,這個(gè)網(wǎng)站一個(gè)小時(shí)就掛五分鐘,你還玩嗎?)

  第二則是這種方式清理出來的空閑內(nèi)存不連續(xù),這點(diǎn)不難理解,我們的死亡對象都是隨即的出現(xiàn)在內(nèi)存的各個(gè)角落的,現(xiàn)在把它們清除之后,內(nèi)存的布局自然會亂七八糟。而為了應(yīng)付這一點(diǎn),JVM就不得不維持一個(gè)內(nèi)存的空閑列表,這又是一種開銷。而且在分配數(shù)組對象的時(shí)候,尋找連續(xù)的內(nèi)存空間會不太好找。

  2 復(fù)制算法(適用于年輕代GC)

  (1)概念:內(nèi)存空間分為兩塊,每次只使用其中一塊,在垃圾回收時(shí),將正在使用的內(nèi)存中的存活對象復(fù)制到未使用的內(nèi)存塊中,之后,清除正在使用的內(nèi)存塊中的所有對象,交換兩個(gè)內(nèi)存的角色,完成垃圾回收。

  與標(biāo)記-清除算法相比,復(fù)制算法是一種相對高效的回收方法,且內(nèi)存連續(xù)。

  不適用于存活對象較多的場合,如老年代(復(fù)制算法適合做新生代的GC)

  (2)優(yōu)點(diǎn):實(shí)現(xiàn)簡單,運(yùn)行高效,內(nèi)存連續(xù)。每次只要一動(dòng)指針,就可聯(lián)系分配內(nèi)存存放復(fù)制過來的對象。

  缺點(diǎn):空間浪費(fèi),只用了一半內(nèi)存,所以,要想用復(fù)制算法,最起碼對象的存活率要非常低才行,而且最重要的是要克服50%內(nèi)存的浪費(fèi)。

  針對這種缺點(diǎn),這種算法比較適合,且已經(jīng)用于年輕代垃圾回收,新生代中的對象98%都是“朝生夕死”的,所以并不需要按照1:1的比例來劃分內(nèi)存空間,而是將內(nèi)存分為一塊比較大的Eden空間和兩塊較小的Survivor空間,每次使用Eden和其中一塊Survivor。當(dāng)回收時(shí),將Eden和Survivor中還存活著的對象一次性地復(fù)制到另外一塊Survivor空間上,最后清理掉Eden和剛才用過的Survivor空間。HotSpot虛擬機(jī)默認(rèn)Eden和Survivor的大小比例是8:1,也就是說,每次新生代中可用內(nèi)存空間為整個(gè)新生代容量的90%(80%+10%),只有10%的空間會被浪費(fèi)。

  當(dāng)然,98%的對象可回收只是一般場景下的數(shù)據(jù),我們沒有辦法保證每次回收都只有不多于10%的對象存活,當(dāng)Survivor空間不夠用時(shí),需要依賴于老年代進(jìn)行分配擔(dān)保,所以大對象直接進(jìn)入老年代。

  標(biāo)記-整理算法(適用于年老代的GC)

  (1)引入:如果在對象存活率較高時(shí)就要進(jìn)行較多的復(fù)制操作,效率將會變低。更關(guān)鍵的是,如果不想浪費(fèi)50%的空間,就需要有額外的空間進(jìn)行分配擔(dān)保,以應(yīng)對被使用的內(nèi)存中所有對象都100%存活的極端情況,所以在老年代一般不能直接選中這種算法。

  (2)概念: 適合用于存活對象較多的場合,如老年代。它在標(biāo)記-清除算法的基礎(chǔ)上做了一些優(yōu)化。和標(biāo)記-清除算法一樣,標(biāo)記-壓縮算法也首先需要從根節(jié)點(diǎn)開始,對所有可達(dá)對象做一次標(biāo)記;但之后,它并不簡單的清理未標(biāo)記的對象,而是將所有的存活對象壓縮到內(nèi)存的一端;之后,清理邊界外所有的空間。

  標(biāo)記:它的第一個(gè)階段與標(biāo)記/清除算法是一模一樣的,均是遍歷GC Roots,然后將存活的對象標(biāo)記。

  整理:移動(dòng)所有存活的對象,按照內(nèi)存地址次序依次排列,然后將末端內(nèi)存地址以后的內(nèi)存全部回收。因此,第二階段才稱為整理階段。(JVM只需要持有一個(gè)內(nèi)存的起始地址即可,這比維護(hù)一個(gè)空閑列表顯然少了許多開銷)

  (3)優(yōu)點(diǎn):標(biāo)記/整理算法不僅可以彌補(bǔ)標(biāo)記/清除算法當(dāng)中,內(nèi)存區(qū)域分散的缺點(diǎn),也消除了復(fù)制算法當(dāng)中,內(nèi)存減半的高額代價(jià)。

  缺點(diǎn):就是效率也不高。不僅要標(biāo)記所有存活對象,還要整理所有存活對象的引用地址。從效率上來說,要低于復(fù)制算法。

  標(biāo)記-清除算法、復(fù)制算法、標(biāo)記整理算法的總結(jié)

  三個(gè)算法都基于根搜索算法去判斷一個(gè)對象是否應(yīng)該被回收,而支撐根搜索算法可以正常工作的理論依據(jù),就是語法中變量作用域的相關(guān)內(nèi)容。因此,要想防止內(nèi)存泄露,最根本的辦法就是掌握好變量作用域,而不應(yīng)該使用C/C++式內(nèi)存管理方式。

  在GC線程開啟時(shí),或者說GC過程開始時(shí),它們都要暫停應(yīng)用程序(stop the world)。

  它們的區(qū)別如下:

  (1)效率:復(fù)制算法 > 標(biāo)記/整理算法 > 標(biāo)記/清除算法

  (2)內(nèi)存整齊度:復(fù)制算法=標(biāo)記/整理算法>標(biāo)記/清除算法

  (3)內(nèi)存利用率:標(biāo)記/整理算法=標(biāo)記/清除算法>復(fù)制算法

  注1:可以看到標(biāo)記/清除算法是比較落后的算法了,但是后兩種算法卻是在此基礎(chǔ)上建立的。

  注2:時(shí)間與空間不可兼得。

  更多關(guān)于“Java培訓(xùn)”的問題,歡迎咨詢千鋒教育在線名師。千鋒已有十余年的培訓(xùn)經(jīng)驗(yàn),課程大綱更科學(xué)更專業(yè),有針對零基礎(chǔ)的就業(yè)班,有針對想提升技術(shù)的好程序員班,高品質(zhì)課程助理你實(shí)現(xiàn)java程序員夢想。

tags:
聲明:本站稿件版權(quán)均屬千鋒教育所有,未經(jīng)許可不得擅自轉(zhuǎn)載。
10年以上業(yè)內(nèi)強(qiáng)師集結(jié),手把手帶你蛻變精英
請您保持通訊暢通,專屬學(xué)習(xí)老師24小時(shí)內(nèi)將與您1V1溝通
免費(fèi)領(lǐng)取
今日已有369人領(lǐng)取成功
劉同學(xué) 138****2860 剛剛成功領(lǐng)取
王同學(xué) 131****2015 剛剛成功領(lǐng)取
張同學(xué) 133****4652 剛剛成功領(lǐng)取
李同學(xué) 135****8607 剛剛成功領(lǐng)取
楊同學(xué) 132****5667 剛剛成功領(lǐng)取
岳同學(xué) 134****6652 剛剛成功領(lǐng)取
梁同學(xué) 157****2950 剛剛成功領(lǐng)取
劉同學(xué) 189****1015 剛剛成功領(lǐng)取
張同學(xué) 155****4678 剛剛成功領(lǐng)取
鄒同學(xué) 139****2907 剛剛成功領(lǐng)取
董同學(xué) 138****2867 剛剛成功領(lǐng)取
周同學(xué) 136****3602 剛剛成功領(lǐng)取
相關(guān)推薦HOT
抖音小店怎么做代銷

抖音已經(jīng)成為了一個(gè)非常受歡迎的短視頻應(yīng)用程序,在其中許多用戶都精心打造了自己的小店,用于銷售各種各樣的商品,獲取額外的收入。然而,要想...詳情>>

2023-10-08 15:28:41
怎樣開抖音小店帶貨賺錢

隨著直播帶貨的火熱,越來越多的人開始嘗試通過抖音小店來開展帶貨業(yè)務(wù)。抖音小店是抖音直播帶貨的配套,可以讓用戶在購買直播中產(chǎn)品時(shí)就實(shí)現(xiàn)購...詳情>>

2023-10-08 15:06:36
能不能幫我打開抖音小店店鋪呢怎么弄

抖音小店是近年來非常火爆的一個(gè)網(wǎng)絡(luò)業(yè)務(wù),也是提供了很多商業(yè)機(jī)會的平臺。對于一個(gè)創(chuàng)業(yè)者而言,開設(shè)抖音小店是一個(gè)不錯(cuò)的選擇。但是,許多小店...詳情>>

2023-10-08 15:01:21
藍(lán)v抖音小店怎么開通店鋪

藍(lán)v抖音小店是一個(gè)非常熱門的電商平臺,它可以讓賣家在抖音上開設(shè)自己的店鋪,從而出售自己的商品。隨著抖音的不斷發(fā)展壯大,越來越多的賣家希...詳情>>

2023-10-08 14:51:53
抖音小店怎么更改類目名稱

抖音小店是現(xiàn)在非常火熱的一種網(wǎng)店形態(tài),許多小生意也從中獲得了收益。但是隨著經(jīng)營時(shí)間的增長,小店也需要對自己的類目名稱進(jìn)行更改,因?yàn)檫@可...詳情>>

2023-10-08 14:46:50
主站蜘蛛池模板: 国产白嫩美女在线观看| 免费1夜情网站| 日本高清免费一本视频无需下载| 夜夜躁狠狠躁日日躁视频| 再深点灬舒服灬太大了老板| 精品一区二区三区在线观看视频| 久久精品国产99久久99久久久 | 久久天天躁夜夜躁狠狠85台湾| 国产福利影院在线观看| 一二三四社区在线中文视频| 女人被男人躁的女爽免费视频| 美国式禁忌3| 久久99国产视频| 狠狠色噜噜狠狠狠狠色吗综合| 成年女人a毛片免费视频| 国产一级毛片大陆| 西西人体www44rt大胆高清| 日鲁鲁| 2022国产麻豆剧果冻传媒影视| 操校花| tube8中国69videos | 在线视频这里只有精品| 免费v片| 国产无套在线观看视频| 国产福利一区二区三区在线观看 | а√最新版在线天堂| 中文字幕在线视频免费观看| 国产69精品久久久久妇女| 小明天天看成人免费看| 强行被公侵犯奈奈美| 欧美最猛黑人xxxx黑人猛交黄| a国产乱理伦片在线观看夜| 国产福利影院| 亚洲剧场午夜在线观看| 蜜挑成熟时k8经典网| 麻豆三级视频| 妞干网在线观看视频| 扒开老师的蕾丝内裤漫画 | 国产一区二区三区不卡在线观看| 3d动漫精品一区二区三区| 真实国产乱子伦对白视频|