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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

JVM垃圾清除算法

發(fā)布時間:2024/1/8 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JVM垃圾清除算法 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言:大家好,我是小威,24屆畢業(yè)生,在一家滿意的公司實習。本篇將記錄幾次面試中經(jīng)常被問到的知識點以及對學習的知識點總結和面試題的復盤。
本篇文章記錄的基礎知識,適合在學Java的小白,也適合復習中,面試中的大佬🤩🤩。
如果文章有什么需要改進的地方還請大佬不吝賜教👏👏。
小威在此先感謝各位大佬啦~~🤞🤞

🏠個人主頁:小威要向諸佬學習呀
🧑個人簡介:大家好,我是小威,一個想要與大家共同進步的男人😉😉
目前狀況🎉:24屆畢業(yè)生,在一家滿意的公司實習👏👏

🎁如果大佬在準備面試,可以使用我找實習前用的刷題神器哦刷題神器點這里喲
💕歡迎大家:這里是CSDN,我總結知識的地方,歡迎來到我的博客,我親愛的大佬😘

以下正文開始

文章目錄

  • 🎄JVM線程私有和共享的區(qū)域
  • 🎇線程上下文切換
  • 🍒如何判斷對象是否存活
    • 🍸引用計數(shù)法
    • 🎍可達性分析法
  • 🍖JVM中的垃圾回收算法
    • 🧃標記清除算法
    • 🥫復制算法
    • 🥓標記整理算法
  • 🍨如何判斷變量是否線程安全
  • 🍻最長遞增子序列

🎄JVM線程私有和共享的區(qū)域

JVM線程私有的區(qū)域有:虛擬機棧,本地方法棧,程序計數(shù)器

虛擬機棧:主要存儲方法,局部變量,運行的數(shù)據(jù)。
本地方法棧:主要存儲本地方法(含有Native關鍵字的方法)。
程序計數(shù)器:存儲程序運行位置的字節(jié)碼行號指示器。

JVM線程共享的區(qū)域有:Java堆,元空間

Java堆:存儲所有創(chuàng)建的對象,數(shù)組等。
元空間:存儲虛擬機加載的字節(jié)碼數(shù)據(jù),常量,靜態(tài)變量,運行時常量池等。

🎇線程上下文切換

線程上下文切換,也就是CPU不再執(zhí)行當前的線程,而去執(zhí)行其他的線程。那有哪些原因會導致線程的上下文切換呢?

  • 線程的時間片用完
  • 垃圾回收(會暫停當前工作的線程,先進行垃圾回收)
  • 更高優(yōu)先級的線程運行
  • 線程主動調用了某些方法,如sleep,yeild,wait,join,synchronized,lock等
  • 當發(fā)生上下文切換時,操作系統(tǒng)會保存當前線程的狀態(tài),恢復另一個線程的狀態(tài),此時程序計數(shù)器會記住下一條jvm指令的執(zhí)行地址,同時上文記錄,程序計數(shù)器是線程私有的

    🍒如何判斷對象是否存活

    判斷對象是否存活有兩種方法:引用計數(shù)算法和可達性分析算法

    🍸引用計數(shù)法

    在對象被創(chuàng)建的時候,會在對象頭中分配一個空間,即計時器,來保存這個對象被引用的次數(shù)。如果這個對象被其他的對象引用,它的引用計數(shù)器會+1,如果刪除其他對象對這個對象的引用,則它的引用計數(shù)會-1,當對象的引用計數(shù)為0時,這個對象就會被當成垃圾回收。

    優(yōu)點:
    引用計數(shù)法實現(xiàn)起來比較簡單,判斷對象是否存活的效率比較高。
    缺點:
    無法解決對象之間循環(huán)引用的問題,不能檢測到環(huán)的出現(xiàn)。例如,A和B之間相互引用,此時計數(shù)器都會顯示為1,此時A和B都無法進行垃圾回收。

    🎍可達性分析法

    Java虛擬機中的垃圾回收機制都是采用的可達性分析算法來探索存活的對象的。此種方法工作原理是會掃描java堆中的對象,沿著GC Roots對象往下尋找,看看是否能在此引用鏈中找到該對象,如果找不到的話,證明該對象沒用了,表示該對象可以回收。

    可達性分析算法最大的優(yōu)點之一就是解決了對象之間的相互循環(huán)依賴的問題,目前和引用計數(shù)法比起來沒有缺點

    🍖JVM中的垃圾回收算法

    對于新生代和老年代的對象,在JVM中會采取不同的垃圾回收算法。年輕代的對象一般都是朝生暮死的,創(chuàng)建之后很快就會被回收,而老年代的對象是需要長期存活的,因此用到的算法大不相同。新生代對應的收集方法為“Minor GC”,老年代對應的收集方法稱為“Major GC”,而對于整個堆空間和方法區(qū)的回收被稱為“Full GC”

    🧃標記清除算法

    標記清除算法為最基礎的垃圾收集算法,即為每個對象都分配一個標記為,這個標記位會記錄對象的狀態(tài)。標記著所要回收的對象,在標記完成后,統(tǒng)一回收掉所有被標記的對象,也可以標記存活的對象,清理掉未標記的對象。標記清除算法用于老年代的垃圾回收中

    優(yōu)點: 基于可達性分析算法,實現(xiàn)起來比較簡單,后續(xù)的算法都是基于這種思想來實現(xiàn)的。
    缺點:
    影響最大的一點在于,標記清除算法會使內存空間碎片化,即標記并清除垃圾后,會產生很多不連續(xù)的內存空間,這將導致較大的對象因為無法找到連續(xù)的內存而提前觸發(fā)一次垃圾回收。

    如果大部分對象需要回收,就會進行大量的標記和清除操作,存活對象數(shù)量多時效率會降低

    🥫復制算法

    復制算法被用于新生代的垃圾回收機制中,新生代有三部分,Eden(80%),和兩個survivor區(qū)(From Survivor 和 To Survivor)。兩個Survivor區(qū)為容量大小相等的兩塊內存,每次只使用其中的一塊內存,當使用的那塊內存用完后,就會將內存中還存活著的對象復制到另一塊內存上,然后把使用過的那塊內存空間清空。

    優(yōu)點: 實現(xiàn)起來比較簡單,效率也比較高,可以保證內存有連續(xù)的區(qū)域能夠解決標記清除算法導致的內存碎片問題。
    缺點:
    可分配的內存空間縮小了一半兒,代價比較高,內存空間浪費比較多; 存活的對象比較多的時候使用復制算法將會導致效率降低。
    進行標記清除算法時,會導致應用程序掛起(停頓),即stop the world(STW)。

    擴展:
    90%以上的對象都是朝生暮死的,所以在新生代中,每次為對象分配內存時會使用Eden區(qū)和其中的一塊Survivor區(qū),當發(fā)生垃圾回收時,JVM會將Eden和Survivor中存活的對象都復制到另一塊Survivor區(qū)域內,之后清理掉Eden區(qū)和Survivor區(qū)域中的空間。綜上所述,建立新對象時,新生代可用內存空間為整個兒新生代容量的90%(80%的Eden區(qū)和10%的Survivor區(qū)),如果發(fā)生了極少部分情況,即多于10%的對象存活下來了,沒有被垃圾回收器回收掉,此時JVM會觸發(fā)空間擔保機制,即當Survivor空間不足以容納一次Minor GC后的存活對象時,就需要依賴老年代進行分配擔保。

    🥓標記整理算法

    標記整理法是對標記清除算法的一個改進。第一個階段和標記清除算法一樣,都是將對象標記為存活和死亡狀態(tài),然而在第二階段,標記清除算法只是將被標記的對象進行清除,標記整理算法會將存活的對象進行整理并且放到另一個端,然后再把所有的對象清除掉。
    標記整理算法用于老年代的回收機制中

    優(yōu)點: 不會像垃圾清除算法那樣產生不連續(xù)的內存碎片空間
    不會像復制算法那樣劃分兩個區(qū)域,提高了空間的利用率
    缺點:
    效率上肯定更慢一些,因為多了一步整理的操作過程。

    🍨如何判斷變量是否線程安全

    對于成員變量和靜態(tài)變量

    • 如果它們沒有被共享,則它們是線程安全的;
    • 如果它們被共享了,根據(jù)它們的狀態(tài)是否能夠改變,又會分兩種情況:如果只有讀操作,則它們是線程安全的;如果有讀寫操作,則這段代碼是臨界區(qū),是需要考慮線程安全的。

    對于局部變量是否線程安全

    • 局部變量是線程安全的
    • 但局部變量引用的對象則未必線程安全。如果該對象沒有逃離方法的作用訪問,它是線程安全的;如果該對象逃離方法的作用范圍,則是需要考慮線程安全的。

    🍻最長遞增子序列

    給你一個整數(shù)數(shù)組 nums ,找到其中最長嚴格遞增子序列的長度。

    子序列 是由數(shù)組派生而來的序列,刪除(或不刪除)數(shù)組中的元素而不改變其余元素的順序。例如,[3,6,2,7] 是數(shù)組 [0,3,1,6,2,2,7] 的子序列。

    示例 1:

    輸入:nums = [10,9,2,5,3,7,101,18]
    輸出:4
    解釋:最長遞增子序列是 [2,3,7,101],因此長度為 4 。

    示例 2:

    輸入:nums = [0,1,0,3,2,3]
    輸出:4

    示例 3:

    輸入:nums = [7,7,7,7,7,7,7]
    輸出:1

    思路:該題讓求出最長的遞增子序列,因此至少需要一次遍歷,考慮到代碼進行到每一步的狀態(tài)才可以,所以動態(tài)規(guī)劃法解決此題比較容易。

    代碼+詳解:

    class Solution {public int lengthOfLIS(int[] nums) {if(nums.length==0){return 0; //長度為0直接返回0}int [] dp=new int[nums.length];dp[0]=1; //初始化數(shù)組,也可以調用庫函數(shù)Arrays.fill(dp,1),但是效率會慢些int result=1;//初始化結果for(int i=1;i<nums.length;i++){dp[i]=1;//初始化數(shù)組for(int j=0;j<i;j++){if(nums[j]<nums[i]){dp[i]=Math.max(dp[i],dp[j]+1);//循環(huán)更新dp[i]的最大值}}result=Math.max(result,dp[i]);}return result;} }

    文章到這里就結束了,如果有什么疑問的地方請指出,諸佬們一起討論🍻
    希望能和諸佬們一起努力,今后進入到心儀的公司
    再次感謝各位小伙伴兒們的支持🤞

    總結

    以上是生活随笔為你收集整理的JVM垃圾清除算法的全部內容,希望文章能夠幫你解決所遇到的問題。

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