-
託管語言(managed language)
-
託管運行時系統(managed run-time system)
-
動態內存分配(allocation)
- 存在於堆(heap)
- 動態
- 遞歸
- 閉包
- 函數式
- 通過*引用(reference)*進行訪問
- 通常,引用即指向對象的指針(pointer)
- 對象在內存中的地址
- 間接訪問時,則使用句柄(handle)
- 好處在於:遷移某一對象時,避免通過程序改變這個對象或句柄的所有引用
- 通常,引用即指向對象的指針(pointer)
- 而非棧(stack)
- 程序的活動記錄(activation record)、棧幀(stack frame)
- 或者靜態區(statically)
- 編譯器或者連接期就可以確定範圍的存儲區域
- 存在於堆(heap)
內存管理的幾種常見策略:
- 顯式釋放(explicit deallocation)策略
- 手動管理
- C
free
- C++
delete
- C
- 基於引用計數
- 追蹤式垃圾回收器
- 風險
- 懸掛指針(dangling pointer)
- 使用*肥指針(fat pointer)*檢測
- 將指針目標對象的版本號作爲指針本身的一部分
- 使用*肥指針(fat pointer)*檢測
- 內存泄露(memory leak)
- 併發問題
- 死鎖(deadlock)
- 活鎖(livelock)
- ABA問題(ABA probleam)
- 懸掛指針(dangling pointer)
- 手動管理
規避內存管理中,存活性問題的幾種思路:
- 棧上分配
- 創建對象的函數返回之後,棧的彈出(pop)操作會自動將對象釋放
- 值傳遞
- 對象池(pool of object)
- 程序某個階段完成之後,池中的對象整體全部釋放
- 特殊指針、模板
- 堆指針操作進行重載(overload)
- 智能指針(smart pointer),兼容性問題
- unique_ptr
- 嚴格的所有權控制語義
- 指針被摧毀時,其目標對象將自動得到釋放
- shared_ptr
- 基於引用計數
- 無法處理自引用(環狀引用)的數據結構
- 只適用於管理:
- 數據塊非常大
- 引用關係變更較少
- 堆指針操作進行重載(overload)
自動動態內存管理
- 垃圾回收(garbage collection,GC)
- 追蹤式回收(tracing collection)
- 垃圾
- 不再使用的對象
- 只有回收器可以釋放對象
- 避免*二次釋放(double-freeing)*問題
- 回收器掌握堆中對象的全局信息以及所有可能訪問堆中對象的線程信息
- 因此,可以決定任意對象是否需要回收
垃圾回收算法的考量指標:
- 安全性
- 吞吐量
- 完整性
- 及時性
- 停頓時間
- 空間開銷
- 針對特定語言的優化
- 可擴展性與可移植性
賦值器、回收器性能需要平衡:
- 最小賦值器使用率(minimum mutator utilization,MMU)
- 界限賦值器使用率(bounded mutator utilization,BMU)
實時基準檢測,自適應策略
垃圾回收算法基本概念:
- 堆
- 由一段或者幾段連續內存組成的空間集合
- 內存顆粒(granule)
- 堆內存分配的最小單位
- 一般爲一個字(word),或者一個雙字(double-word)
- 取決於對齊(alignment)方式
- 內存塊(chunk)
- 一組較大的連續內存顆粒
- 依據特定大小對齊的大塊內存
- 內存單元(cell)
- 由數個連續顆粒組成的小內存塊
- 通常用於內存的分配和釋放
- 對象
- 應用程序分配的內存單元
- 通常是一段可尋址的連續字節或字的數組
- 內部被劃分成多個槽(slot)或者域(field)
- 對象頭
- 用一個頭域(header field)來存放運行時系統會用到的元數據
- 對象圖(object graph)
- 有向圖(directed graph)
- 圖的節點(node)是堆中的對象
- 有向邊是對象之間的引用
- 邊一般是從源節點(source node)或者根(root)指向目標節點(destination node)的引用
- 幀(frame)
- 一大段2^k大小的地址空間
- 空間(space)
- 由一系列(可能)不連續的內存塊組成的集合
- 頁(page)
- 由硬件以及操作系統的虛擬內存機制定義
- 高速緩存行(cache line)、高速緩存塊(cache block)
- 由CPU的高速緩存(cache)
- 卡(card)
- 以2的整數次冪對齊的內存塊
- 一般小於一頁
- 通常與某些跨空間指針的方案有關
- 賦值器
- 執行應用代碼
- 分配新的對象
- 修改對象之間的引用關係
- 改變堆中對象圖的拓撲結構
- 回收器
- 執行垃圾回收代碼
- 找到不可達對象並將其回收
- 執行垃圾回收代碼
- 賦值器根
- 一個有限的指針集合
- 賦值器可以不經過其他對象直接訪問這些指針
- 根對象(root object)
- 堆中直接由賦值器根所引用的對象
- 引用
- 通常是一個正規指針(canonical pointer)
- 指向對象頭部(即對象首地址)
- 或者距頭部有一定偏移量的地址
- 派生指針(derived pointer)
- 一般是在對象的正規指針的基礎上增加一個偏移量而得到的指針
- 內部指針(interior pointer)
- 指向內部對象域的派生指針
- 通常是一個正規指針(canonical pointer)
- 域
- 可能會包含一些非引用的純數據
- 地址
- 存活性
- 能被賦值器訪問,則該對象存活
- 不論是否被使用
- 指針可達
- 分配器(allocator)
- 分配(allocate)
- 爲某一對象保留底層的內存存儲
- 釋放(free)
- 將內存歸還給分配器以便複用
- 分配(allocate)
- 賦值器讀寫操作
- 創建(New)
- 從堆分配器中獲得一個新的堆對象
- 分配器返回新分配的對象首地址
- 讀(Read)
- 指向對象的指針
- 待訪問的域的索引號
- 寫(Write)
- 引發內存存儲
- 指向元對象的指針
- 待修改域的索引號
- 待存儲的值(純值或者指針)
- 使用屏障(barrier)
- 會同步或者異步的與回收器產生交互
- 讀屏障(read barrier)
- 寫屏障(write barriter)
- 創建(New)
- 原子操作
- 掛起賦值器
- 確保垃圾回收過程的原子性(atomically)
- 垃圾回收過程中賦值器不會訪問堆中對象
- 掛起賦值器
- 集合
- set
- 存放不同元素的容器(元素兩兩不同)
- 集合中元素的數量稱爲基(cardinaliy),寫作:|S|
- 多集合
- multiset
- 內部允許存在相同元素
- 某一元素出現的次數稱爲該元素的重數(multiplicity)
- 符號:[]
- 序列
- sequence
- 可重複,有順序
- 符號:()
- 元組
- tuple
- 長度不變
- 符號:<>