深入理解Java虛擬機---垃圾收集算法

深入理解Java虛擬機---垃圾收集算法

  • 如何判定對象是否存活
    • 引用計數法
    • 可達性分析法
  • Java引用類型
  • 垃圾回收算法
    • 標記-清除算法
    • 復制算法
    • 標記-整理算法
    • 分代收集算法
  • HotSpot的算法實現
    • 枚舉根節點
    • 安全點
    • 安全區域

如何判定對象是否存活

引用計數法

引用計數算法利用額外的內存空間來進行計數,在對象中添加一個引用計數器,每當有一個地方引用它時,計數器值就加一;當引用失效時,計數器值就減一;任何時刻計數器為零的對象就是不可能再被使用的。

可達性分析法

基本思路就是通過一系列稱為GC Roots的根對象作為起始節點集,從這些節點開始,根據引用關系向下搜索,搜索過程所走過的路徑稱為“引用鏈”, 如果某個對象到GC Roots間沒有任何引用鏈相連,則此對象不可能再被使用。
在可達性分析算法中判定為不可達的對象,至少要經歷兩次標記過程才能被銷毀:(1)如果對象在進行可達性分析后 發現沒有與GC Roots相連接的引用鏈,那它將會被第一次標記,(2)隨后進行一次篩選, 篩選的條件是此對象是否有必要執行finalize()方法。 假如對象:沒有覆蓋finalize()方法或者finalize()方法已經被虛擬機調用過了一次 ,虛擬機將此情況視為“沒有必要執行”。
Java技術體系中,可作為GC Roots的對象包括以下幾種:
(1)虛擬機棧(棧幀中的本地變量表)中引用的對象 ,譬如各個線程被調用的方法堆棧中使用到的參數、局部變量、臨時變量等。
(2)方法區中類靜態屬性引用的對象 ,如Java類的引用類型靜態變量。
(3)在方法區中常量引用的對象 ,如字符串常量池里的引用。
(4)在本地方法棧中JNI引用的對象。

Java引用類型

Java中引用分為以下四類:
強引用
就是指在程序代碼之中普遍存在的,類似“Object obj = new Object()”這類的引用,只要強引用還存在,垃圾收集器永遠不會回收掉被引用的對象。
軟引用
用來描述一些還有用,但并非必需的對象。對于軟引用關聯著的對象,在系統將要發生內存溢出異常之前,將會把這些對象列進回收范圍之中并進行第二次回收。如果這次回收還是沒有足夠的內存,才會拋出內存溢出異常。在JDK1.2之后,提供了 SoftReference類來實現軟引用。
弱引用
用來描述非必需對象的,但是它的強度比軟引用更弱一些,被弱引用關聯的對象只能生存到下一次垃圾收集發生之前。當垃圾收集器工作時,無論當前內存是否足夠,都會回收掉只被弱引用關聯的對象。在 JDK 1.2之后,提供了WeakReference類來實現弱引用。
虛引用
稱為幽靈引用或者幻影引用,它是最弱的一種引用關系。一個對象是否有虛引用的存在,完全不會對其生存時間構成影響,也無法通過虛引用來取得一個對象實例。為一個對象設置虛引用關聯的唯一目的就是希望能在這個對象被收集器回收時收到一個系統通知。在JDK 1.2之后,提供了PhantomReference類來實現虛引用。

垃圾回收算法

標記-清除算法

算法分為“標記”和“清除”兩個階段:首先標記出所有需要回收的對象,在標記完成后統一回收所有被標記的對象。
標記清除算法主要有兩個不足:
(1)效率問題,標記和清除兩個過程的效率都不高;
(2)空間問題,標記清除之后會產生大量不連續的內存碎片,空間碎片太多可能會導致以后在程序運行過程中需要分配較大對象時,無法找到足夠的連續內存而不得不提前觸發另一次垃圾收集動作。

復制算法

將可用內存按容量劃分為大小相等的兩塊,每次只使用其中的一塊。當這一塊的內存用完了,就將還存活著的對象復制到另外一塊上面,然后再把已使用過的內存空間一次清理掉。

標記-整理算法

標記-整理”算法,標記過程仍然與“標記-清除”算法一樣,但后續步驟不是直接對可回收對象進行清理,而是讓所有存活的對象都向一端移動,然后直接清理掉端邊界以外的內存。

分代收集算法

根據對象存活周期的不同將內存劃分為幾塊。一般把Java堆分為新生代和老年代,這樣就可以根據各個年代的特點采用最適當的收集算法。在新生代中,每次垃圾收集時都發現有大批對象死去,只有少量存活,那就選用復制算法,只需要付出少量存活對象的復制成本就可以完成收集。而在老年代中因為對象存活率高、沒有額外空間對它進行分配擔保,就必須使用“標記-清理”或者“標記-整理”算法來進行回收。

HotSpot的算法實現

枚舉根節點

在HotSpot的實現中,使用一組稱為OopMap的數據結構來得知哪些地方存放著對象引用,在類加載完成的時候,HotSpot就把對象內什么偏移量上是什么類型的數據計算出來,在JIT編譯過程中,也會在特定的位置記錄下棧和寄存器中哪些位置是引用。這樣,GC在掃描時就可以直接得知這些信息。

安全點

在OopMap的協助下,HotSpot可以快速且準確地完成GC Roots枚舉,但可能導致引用關系變化或者OopMap內容變化的指令非常多,如果為每一條指令都生成對應的OopMap,那將會需要大量的額外空間,GC的空間成本將會變高。
HotSpot也的確沒有為每條指令都生成OopMap,只是在“特定的位置”記錄了這些信息,這些位置稱為安全點,即程序執行時并非在所有地方都能停頓下來開始GC,只有在達到安全點時才能暫停。安全點的選定基本上是以程序“是否具有讓程序長時間執行的特征”為標準進行選定的——因為每條指令執行的時間都非常短暫,程序不太可能因為指令流長度太長這個原因而過長時間運行,“長時間執行”的最明顯特征就是指令序列復用,例如方法調用、循環跳轉、異常跳轉等,所以具有這些功能的指令才會產生安全點。
對于安全點,另一個需要考慮的問題是如何在GC發生時讓所有線程(不包括執行JNI調用的線程)都“跑”到最近的安全點上再停頓下來。這里有兩種方案可供選擇:搶先式中斷和主動式中斷,其中搶先式中斷不需要線程的執行代碼主動去配合,在GC發生時,首先把所有的線程全部中斷,如果發現有線程中斷的地方不再安全點上,就恢復線程,讓它“跑”到安全點上。現在幾乎沒有虛擬機實現采用搶先式中斷來暫停線程從而響應GC事件的。而主動式中斷的思想是當GC需要中斷線程的時候,不直接對線程操作,僅僅簡單地設置一個標志,各個線程執行時主動去輪詢這個標志,發現中斷標志為真時就自己中斷掛起。輪詢標志的地方和安全點是重合的,另外再加上創建對象需要分配內存的地方。

安全區域

安全點機制保證了程序執行時,在不太長的時間內就會遇到可進入GC的安全點,但是程序沒有被分配到CPU時間,典型的例子就是線程處于Sleep狀態或者Blocked狀態,這時候線程無法響應JVM的中斷請求,“走”到安全的地方去中斷掛起,JVM也顯然不太可能等待線程重新被分配CPU時間。對于這種情況,就需要安全區域來解決。安全區域是指在一段代碼片段之中,引用關系不會發生變化。在這個區域中的任意地方開始GC都是安全的。在線程執行到安全區域中的代碼時,首先標記自己已經進入了安全區域,那樣,當在這段時間里JVM要發起GC時,就不用管標志自己為安全區域狀態的線程了。在線程要離開安全區域時,它要檢查系統是否已經完成了根節點枚舉,如果完成了,那線程就繼續執行,否則它就必須等待直到收到可以安全離開安全區域的信號為止。

來源:《深入理解Java虛擬機》

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/215305.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/215305.shtml
英文地址,請注明出處:http://en.pswp.cn/news/215305.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Dockerfile創建鏡像介紹

1.介紹 Docker 提供了一種更便捷的方式&#xff0c;叫作 Dockerfile&#xff0c;docker build命令用于根據給定的Dockerfile構建Docker鏡像。 docker build語法&#xff1a; # docker build [OPTIONS] <PATH | URL | -> 常用選項說明 --build-arg&#xff0c;設置構建時的…

上海亞商投顧:滬指探底回升 AI應用方向再度爆發

上海亞商投顧前言&#xff1a;無懼大盤漲跌&#xff0c;解密龍虎榜資金&#xff0c;跟蹤一線游資和機構資金動向&#xff0c;識別短期熱點和強勢個股。 一.市場情緒 三大指數昨日探底回升&#xff0c;早盤一度均跌超1%&#xff0c;午后集體拉升翻紅&#xff0c;深成指、創業板…

FFmpeg的AVcodecParser

文章目錄 結構體操作函數支持的AVCodecParser 這個模塊是AVCodec中的子模塊&#xff0c;專門用來提前解析碼流的元數據&#xff0c;為后面的解碼做準備&#xff0c;這一點對cuda-NVdec非常明顯&#xff0c;英偉達解碼器的元數據解析是放在CPU上的&#xff0c;所以就非常依賴這個…

為什么Vue3的proxy需要Reflect呢

何為proxy Proxy 對象用于定義或修改某些操作的自定義行為&#xff0c;可以在外界對目標對象進行訪問前&#xff0c;對外界的訪問進行改寫。 var proxy new Proxy(target, handler)ES6 中的proxy目前提供了13種可代理操作攔截的行為。 何為reflect ES6 標準中&#xff0c;…

遠程工作:自由職業者如何成功賺錢

前言 在這個不斷進步的數字化時代&#xff0c;遠程工作已經從一個可選的邊緣工作方式&#xff0c;成長為主流職業趨勢的一部分。特別是自從全球疫情改變了我們的生活和工作方式以來&#xff0c;遠程工作的概念不再是遙不可及的理想&#xff0c;而是已經成為許多人日常工作的現…

SpringBoot集成swagger2配置權限認證參數

作者簡介&#xff1a;大家好&#xff0c;我是擼代碼的羊駝&#xff0c;前阿里巴巴架構師&#xff0c;現某互聯網公司CTO 聯系v&#xff1a;sulny_ann&#xff08;17362204968&#xff09;&#xff0c;加我進群&#xff0c;大家一起學習&#xff0c;一起進步&#xff0c;一起對抗…

[Java][JDK5]可變參數

我們可以假設一種情況&#xff0c;我們需要進行求和計算 在原先&#xff0c;我們考慮到參數只能傳入一個數字&#xff0c;因此我們會將需要求和的數字放在一個數組&#xff0c;傳入該數組進入方法再拆分計算 比如下面的例子:使用了增強for來對數組進行遍歷 public class Mai…

【Lidar】基于Python的三維點云數據轉二維平面+散點圖繪制

最近一直在搞點云相關的操作&#xff0c;有時候在處理點云數據時需要查看處理后的數據是否滿足需求&#xff0c;所以就想著寫一套展示點云的代碼。之前已經分享過如何可視化點云了&#xff0c;感興趣的可以自己去看下&#xff1a;【Lidar】基于Python的Open3D庫可視化點云數據。…

golang https server如何設計方便抓包定位且安全

代碼 測試 用go寫后端https服務時&#xff0c;需要定位https包中的內容是否符合預期。 有涉獵的朋友應該了解過https有一種keylog技術&#xff0c;它允許在HTTPS連接中捕獲和記錄SSL或TLS會話密鑰&#xff0c;以便于調試和分析加密流量。 本文將的就是通過可控制開啟和關閉的…

單身狗(Python)

題目描述 單身狗 “單身狗”是中文對于單身人士的一種愛稱。本題請你從上萬人的大型派對中找出落單的客人&#xff0c;以便給予特殊關愛。 輸入格式&#xff1a; 輸入第一行給出一個正整數 N&#xff08;≤50000&#xff09;&#xff0c;是已知夫妻/伴侶的對數&#xff1b;…

CPU 混合推理,非常見大模型量化方案:“二三五六” 位量化

本篇文章聊聊網上聊的比較少的具體量化操作&#xff0c;非常見整型位數的量化&#xff0c;來自讓各種開源模型能夠在 CPU 環境、CPU & GPU 環境混合推理的技術方案&#xff1a;llama.cpp 。 寫在前面 接下來&#xff0c;有計劃分享一些關于各種開源模型的實踐內容。為了能…

安裝ThingBox Eclipse Plugin

1. ChatGPT問 The latest version of the ThingBox Eclipse Plugin requires Eclipse IDE 2021-06 or later. 2. PTC官網下載 MED-61378-CD-092_F000_Eclipse-Plugin-9-0-1.zip文件, 和 MED-61098-CD-085_F000_ThingWorx-Extension-SDK-8-5-0&#xff08;需要賬號&#xff09…

虛擬化邏輯架構:KVM虛擬機通過OVS端口組實現網絡連接

目錄 一、實驗 1.CentOS 7 安裝 OpenVSwitch(構建RPM安裝包&#xff09; 2.KVM虛擬機通過OVS端口組實現網絡連接 二、問題 1.安裝openvswitch-2.5.10報錯 2.virt-install未找到命令 3.如何刪除自定義網絡 一、實驗 1.CentOS 7 安裝 OpenVSwitch(構建RPM安裝包&#xff…

字符串知識點

一. 1.字符占據一個字節 2.字符數組&#xff1a;char name[15] { W, a, n, g, L, i}; 字符串&#xff1a;char name[15] “Wang Li”&#xff1b; 二. 1.字符串&#xff1a;為有效長度&#xff08;有效字符的個數&#xff09;而不是字符數組的長度&#xff1b; 2.&#…

創建一個有陰影的threejs三維幾何體

import * as THREE from "three" import { OrbitControls } from three/examples/jsm/controls/OrbitControlsconst width window.innerWidth; const height window.innerHeight;//創建場景 const scene new THREE.Scene(); scene.background new THREE.Color(#6…

LinuxBasicsForHackers筆記 --Python 腳本基礎

添加Python模塊 Python 有一個專門用于安裝和管理 Python 包的包管理器&#xff0c;稱為 pip&#xff08;Pip Installs Packages&#xff09;。由于我們在這里使用 Python 3&#xff0c;因此您將需要 Python 3 的 pip 來下載和安裝軟件包。默認情況下應包含 Pip&#xff0c;但…

學習Node.js與Webpack總結

今天學習了模塊化的簡介&#xff0c;其實一個項目是由很多個模塊文件組成的&#xff0c;它們有它們各自的功能和用途來協助這個項目的完成&#xff0c;這樣的模塊組成有很多的好處比如提高代碼的復用性、還可以按需加載、還有獨立的作用域&#xff0c;還需要搞清楚的一點就是No…

如何截取Hive數組中的前N個元素?

文章目錄 1、需求描述2、使用索引3、使用posexplode()4、轉換為字符串操作 1、需求描述 需求&#xff1a;截取任意給定數組中的前N個元素&#xff0c;返回截取后的子數組 假設我們有如下三種類型的Hive數組&#xff1a; select array(1,2,3,4) -- [1,2,3,4] selec…

vue前端訪問Django channels WebSocket失敗

現象 前端報錯&#xff1a;SSH.vue:51 WebSocket connection to ‘ws://127.0.0.1:8000/server/terminal/120.59.88.26/22/1/’ failed: 后端報錯&#xff1a;Not Found: /server/terminal/120.79.83.26/22/1/ 原因 django的版本與channels的版本不匹配&#xff08;django…

關于個人職業選擇

職業選擇&#xff0c;一直是個老生常談的話題。這并不是一個容易做的決定。 讓我們來看看AI怎么說。 首先是方向性的回答&#xff1a; 然后是一些具體的回答 我個人比較傾向于深耕網絡安全。這是一個很有趣也是一個持續發展著的領域。 不知道關于這個事情你怎么看&#xff0…