GC 和虛擬機是兩個一定要放在一起的概念嗎?
常見的垃圾回收都是由虛擬機來執行的,例如JVM或者Lua虛擬機。直觀上來看,相對於引用計數來說,基於跟蹤的垃圾回收做到可執行文件中會比較麻煩,那麼有沒有比較成熟的將垃圾回收做到可執行文件中的方法?
不是。GC和虛擬機從來都不是必須綁定在一起的概念。
雖然GC和虛擬機的概念都是很早很早之前就有了,而且以前也有過若干語言實現(例如Pascal的P-code虛擬機,Smalltalk的GC和虛擬機)一定程度上流行過,但GC與虛擬機的概念廣泛流行起來還是從Java/JVM開始的——看起來它們就像是相互依賴的概念一樣,然而其實這只是個巧合。之後與JVM同類型的.NET(CLR)的流行進一步推動GC與虛擬機的概念被許多人認為是綁在一起的,然後與Java誕生時間相近的Python、Ruby、JavaScript,後來的Lua等語言的流行也更強化了這種印象。
其實GC與(高級語言)虛擬機是兩個完全正交的概念。前者負責自動內存管理,後者可以用於多種用途——跨平台/移植性、安全、語義描述,等等。
碰巧1990-2000年間出現的高級編程語言很流行既要自動內存管理,又要跨平台、安全等特性,就把GC和虛擬機技術結合在了一起。僅此而已。近年來出現的新語言有很多又不流行用虛擬機了,或者不流行用GC了,所以在現在這個時間點上這倆技術又更多的被分開使用。舉幾個例子。使用了GC但是沒有使用「虛擬機」概念的語言/實現:
- Go
- D
- 任何使用了Boehm GC但是沒有使用「虛擬機」概念的東西,例如
- GNU Objective-C runtime
- GCC(對,GCC內部有個GC用來管理其臨時對象。看 ggc-internal.h、gty.texi)
- C4。參考這裡 有哪些關於c4 - C in four function 編譯器的文章? - RednaxelaFX 的回答
- Cint
- 《Virtual Machine Design and Implementation C/C++》所描述的虛擬機
- 用「虛擬機」方式加殼的程序
===================================
順帶,「高級語言虛擬機」(High-Level Language Virtual Machine,HLLVM)其實並不是一個特別明確的說法。更準確的說法是managed runtime——那些沒有虛擬指令集(ISA)的實現也可以包括進來。
GC要做自動內存管理,最重要的功能是要判斷哪些內存是可以回收的,並對其進行回收。需要精確到object粒度的內存的引用分析甚至是移動等操作。
OS提供了基本的內存管理功能,包括分配,回收,以及物理內存和虛擬內存的映射。但是其粒度太粗了,只到page(至少4k)這一層。所以只能在runtime層面對OS的內存管理進行增強,這個跟虛擬機的理念有點類似。就像R大答案裡面說的,因為一些其他方面的需求,本來也要做一層虛擬機,所以就一併做了。
但是我覺得這個融合可以做的更徹底,更通用一些。
因為反過來,虛擬機裡面也有跟gc理念類似的東西。
比如kvm的live migration就跟copy gc有點類似。本來一個虛擬機用了很多內存,可能其中一部分內存已經不需要了,做一個live migration,就可以只把當前正在使用的內存copy過去,甩掉那部分不再使用的內存。如果像最簡單的copy gc一樣,兩個虛擬機來回live migration,就成了虛擬機層面的gc了。
當然這裡面還有很多問題,目前是做不到的。
但是我覺得可以考慮進一步融合。把gc裡面對內存管理增強的部分功能下沉到kvm/Docker之類的虛擬機層面,甚至是OS裡面。如果真的能做到,上層應用將很容易獲得gc的功能,至少比現在每個語言都搞一個要好吧。不是 你也可以專門在c++里寫gc 但是就不能用原生指針了 可以寫一個gc_ptr作為堆內存的指向
本質上是兩碼事,只不過所謂的高層語言既追求跨平台又追求內存自動管理,所以恰好就在一起了。不過GO 是個反例,這貨有GC,但是沒有虛擬機。
話說搞某些存儲硬體的也有gc概念...
命題A:VM是GC機制存在的充要條件。反例:Swift編譯到Native code,有ARC(Automatic reference counting)。結論:命題A是假命題。
推薦閱讀:
※QEMU 開源模擬器有哪些實用?
※虛擬機的cpu架構是什麼樣的?
※虛擬機的系統和程序能判斷出自己是運行在虛擬機上的么?
※Mac OS X Lion 允許在虛擬機中運行多個虛擬 OS X 版本的功能為什麼僅向 Mac OS X Server 開放?
TAG:即時編譯JIT | 虛擬機 | 編譯原理 | GC垃圾回收計算機科學 |