深入概括VB.NET運(yùn)行環(huán)境
隨著時(shí)代的變化,信息成為我們不可缺少的一部分,在這發(fā)展中我們開發(fā)的語言也隨之成長,不管應(yīng)用是用VB、C#還是其他.NET語言編寫,所有VS.NET代碼都是編譯成中間語言(Intermediate Language,IL)。當(dāng)應(yīng)用運(yùn)行時(shí),一個(gè)實(shí)時(shí)編譯器(just-in-time compiler,或稱為JIT)就把IL代碼編譯成機(jī)器語言。在理論上,它意味著為非Windows的平臺(tái)構(gòu)造VB.NET運(yùn)行環(huán)境是可能的,但目前還沒有出現(xiàn)有關(guān)這類系統(tǒng)的正式消息。IL有一個(gè)缺點(diǎn):正如VB在5.0以前的版本,IL代碼對(duì)于類似的反向編譯工程很敏感。由于存在這種可能性,許多開發(fā)者對(duì)于.NET框架的整體安全性抱有懷疑。
對(duì)CLR進(jìn)行優(yōu)化影響IL層次上的代碼,它使得所有使用CLR的語言受益。然而,對(duì)于特定語言的優(yōu)化涉及到如何把代碼編譯成IL代碼,它根據(jù)特定語言的語法進(jìn)行。因此,.NET各種語言之間存在一定的性能差異是必然的。但不管如何,從整體上來看這仍舊是好事,例如CLR為VB帶來了和C#一樣的調(diào)試和分析工具——之所以能夠如此,是因?yàn)樗鼈兌际褂靡粯拥墓ぞ摺?
CLR提供了前所未有的跨語言集成能力,其中包括跨語言繼承代碼的能力。所有使用CLR的語言都使用一個(gè)公共類型系統(tǒng)(Common Type System),它使得開發(fā)那些運(yùn)用多種語言的應(yīng)用變得更為容易。在CLR之內(nèi)運(yùn)行的代碼稱為“受管理的代碼”(Managed Code),受管理代碼所使用的內(nèi)存由CLR全面控制。受管理的代碼有著許多優(yōu)點(diǎn),包括交叉語言集成、跨語言異常控制以及一個(gè)組件交互的簡化模型。VB.NET運(yùn)行環(huán)境只能以受管理代碼方式運(yùn)行,與此相對(duì)應(yīng),C#卻具有將代碼轉(zhuǎn)入非受管理方式運(yùn)行的能力(運(yùn)行在CLR之外),比如執(zhí)行指針處理之類的操作。這是VB.NET不能與C#相提并論的地方之一。然而,這種能力的是否重要,對(duì)于不同的人、不同的用途來說都有所不同。
由CLR導(dǎo)致的體系上的不同不僅僅是跨語言繼承、共享功能和受管理代碼,它還有更深刻的意義。Visual Studio.NET的底層體系不再是COM;另外,VB.NET運(yùn)行環(huán)境中所有東西都是對(duì)象,甚至連字符串也一樣。由于這些原因以及其他許多原因,Microsoft改變了底層體系管理對(duì)象的方法。COM系統(tǒng)通過引用計(jì)數(shù)方式管理對(duì)象,每當(dāng)對(duì)象被引用時(shí),引用計(jì)數(shù)就增加。當(dāng)對(duì)象引用超出作用范圍或者被釋放時(shí),計(jì)數(shù)器的值就減少;一旦引用計(jì)數(shù)為0,對(duì)象就被釋放。Microsoft聲稱.NET體系中的引用計(jì)數(shù)開銷實(shí)在太大,使得.NET采用引用計(jì)數(shù)不再合適,因此它就放棄了引用計(jì)數(shù),改用垃圾回收(Garbage Collection)。
大約40年前,John McCarthy設(shè)計(jì)了LISP語言,它是可考證的第一種編程語言。LISP運(yùn)行時(shí)不斷地分配和釋放大量的小塊內(nèi)存,由于那時(shí)的計(jì)算機(jī)內(nèi)存遠(yuǎn)遠(yuǎn)沒有現(xiàn)在這么龐大,因此早期的LISP用戶很快感到內(nèi)存不足,同時(shí)許多不再使用的內(nèi)存卻未能利用起來。為了解決這個(gè)問題,McCarthy于1959年第一次提出了垃圾回收的思想。
在一個(gè)真正面向?qū)ο蟮南到y(tǒng)中,垃圾回收機(jī)制能夠很好地滿足分配和釋放大量小塊內(nèi)存的需要。因此,Microsoft在VS.NET中重新實(shí)現(xiàn)了垃圾回收機(jī)制。
CLR垃圾回收器(CLR Garbage Collector)的主要任務(wù)就是監(jiān)視程序使用的資源,當(dāng)可用資源達(dá)到某個(gè)確定的極限時(shí)查找不再使用的對(duì)象,如發(fā)現(xiàn)有這類對(duì)象存在則釋放它們所占用的資源。垃圾回收的一個(gè)很大的優(yōu)點(diǎn)是程序員無需再為大多數(shù)常見的循環(huán)引用擔(dān)心。在循環(huán)引用情形下,子對(duì)象擁有對(duì)父對(duì)象的引用,同時(shí)父對(duì)象又擁有對(duì)子對(duì)象的引用。在引用計(jì)數(shù)模式下,循環(huán)引用阻止了系統(tǒng)釋放和拆除任意一個(gè)對(duì)象。然而,垃圾回收器能夠找出這類循環(huán)引用并拆除它們。垃圾回收機(jī)制同時(shí)也意味著,當(dāng)對(duì)象的最后一個(gè)引用被釋放時(shí),對(duì)象并不一定立即被拆除。
采用垃圾回收機(jī)制的一個(gè)后果是:我們不能再希望類的Terminate事件總是適時(shí)觸發(fā)。事實(shí)上,如果線程被阻塞的話,Terminate事件可能完全不會(huì)觸發(fā)。這就是所謂的“非確定的結(jié)束”(non-deterministic finalization),而COM提供的則是“確定的結(jié)束”。由于缺乏“確定的結(jié)束”,再加上因?yàn)槔厥掌髦匦陆M織和整理內(nèi)存導(dǎo)致不能運(yùn)用指針,新聞組中出現(xiàn)了對(duì)該問題激烈的爭論:有些人憎恨這些新的限制,因?yàn)樗麄円蕾囉凇按_定的結(jié)束”;有些人覺得無關(guān)緊要,因?yàn)樗麄儾⒉灰蕾囉赥erminate事件。
從引用計(jì)數(shù)轉(zhuǎn)變到垃圾回收僅僅是Visual Studio.NET底層體系不再是COM這一變化的諸多必然結(jié)果之一。雖然VB.NET之內(nèi)仍舊可以使用COM對(duì)象,但這些對(duì)象必須通過封裝(Wrapper)才能訪問。任何時(shí)候,封裝都意味著性能的降低,甚至還有可能導(dǎo)致對(duì)象行為的異常。如果要遷移一個(gè)大量使用COM對(duì)象的工程,你必須認(rèn)真地進(jìn)行計(jì)劃和測(cè)試,應(yīng)用程序的某些部分可能還需要重新構(gòu)造。
【編輯推薦】