【Xamain 跨平臺機制原理剖析】

原文: 【Xamain 跨平臺機制原理剖析】

【看了請推薦,推薦滿100後,將發補丁地址】php

 

Xamarin項目從喊口號到如今,好幾個年頭了,在內地沒有火起來,緣由無非有三,1.受權費貴 2.貴 3.原生態Java開發Android的愈來愈多,人工費用成本下降。html

上面說的3條,都跟錢相關,不佔技術邊,看起來跟本文的標題嚴重不符。可是,細細看來,若是這個產品的圈子打不開,再牛的技術,也是枉然。由於技術是在不斷推動的,java

性能問題,技術問題,實現問題,等等均可以隨着時間的推進去解決,可是,Xamarin公司貌似沒打算把價格下降。愈加的穩定。死鬼死鬼.......。因此,咱們須要破解,咱們須要破解,咱們須要破解(重要的事情說3遍),可是破解並不是容易,這個平臺軟件,幾乎是我見過的CLI語言最難破解的東東,由於裏面釘子太多,剃不乾淨。(我曾經嘗試去破解,發現須要耗費太多的時間,並且不穩定)。。可是,嗯,道高一尺魔高一丈。找補丁,到谷歌..........如今能夠明確的告訴你們,最新版的Xamarin有了破解補丁。谷歌去吧。android

 

上面說的是題外話,但願這個生態能夠在這片土壤繼續壯大。咱們開始進入咱們的標題,不要說我是標題黨。呵呵。安全

咱們就討論Xamarin的Android開發機制吧,IOS的,自己就是在MAC下面編譯的,是AOT,不是JIT.........AOT機制,自己把代碼轉換成了Native代碼應用。JIT是基於虛擬機語言運行的中間代碼。Java和.Net 都是JIT 。。。。都有相似運行的虛擬機。Java->JVM  .....C#->CLR->JIT->Native Code......微信

 

首先,這個跨平臺的思路是基於好久之前的的Mono項目,關於Mono項目,本身百度腦補。Mono是對微乳.Net的跨平臺的實現。基於C語言的實現,能夠實現CLR在不一樣的平臺系統下的運行。固然,針對的就是Linux系統。Mono的誕生,讓.net能夠在Linux下跑了。框架

好,上面僅僅是開端,咱們再來看下Android。這個項目是Google收購的一家Droid公司的產品。就是用開源的Linux系統,作的二次開發。本質依然是Linux內核。異步

谷歌收購這個項目後,加大了對這個項目的投入。最終得以讓這個項目在移動設備上運行起來。。(資本+科技=進步)ide

看Android項目的結構圖:wordpress

 

  • Applications 應用程序層(由Java編寫而且在Dalvk虛擬機來運行)
  • Framework 應用框架層 (由Java編寫)
  • Libraries And Android Runtime 各類庫和Android 運行環境
  • Linux Kernel 操做系統層

從最上層的應用層,如 短信 電話 視頻 微信 QQ等應用 到先的支持庫,都是用Java實現的。

再往下就是一些對硬件功能包裝的庫lib層,大可能是一些開源的Linux應用庫,跟這個層平級的Android的虛擬機Dalvik。

最終是Linux的內核,系統的內核的做用,就是操做系統跟硬件進行交互。(固然,硬件須要對應的驅動被系統所能識別)

以上是安卓的結構和運行概述。當你打開微信的時候,就是從應用層-》框架層-》虛擬機到內核的一個來回調用交互。

----------------------------------Xamarin是怎麼運行的?----------------------------------

咱們上面說過,Mono項目,實現.net語言在Linux下運行,Android是Linux項目,那隻要Android中有Mono,那麼.net 就能在安卓裏跑!!!!

因而,從Mono開發過的一些人,過分到了Xamarin公司。Xamarin公司就是基於此。

那麼Xamarin打包的安卓應用是怎麼跑的? 看下面的圖:

這是啥?

哦,老伯伯的皮影。

額,被老外學會了。。。。。

而後, 無語了...................

 

沒錯,這個Xamarin其實就是皮影戲(高科技的皮影)!!!!!!!!!!!!!!!!!!!!!

(寫到這裏,不只爲國人悲哀,本身家的東西都被當垃圾丟棄,外國佬卻總能從裏面找出點什麼。。。好比:炸藥 司南 羅盤 等等,咱們本身拋棄了本身,咱們的眼裏腦子裏只有錢錢房房.................拿出點理想吧  my guys!!!)

說它是高科技的皮影,並不是空穴來風。咱們看看官方給出的結構解釋:

原文:

大概意思是:Xamarin安卓項目是基於Mono運行時的,Android原生應用基於安卓運行時,也就是那個Dalvik虛擬機。。。當運行Xamarin建立的安卓應用的時候,

對應的安卓虛擬機上也會有對應包裝過的對象的實例被分配。那個MCW 表明的是對原生Android的Lib的綁定,ACW是基於調用映射的API後返回響應到Mono。

怎麼綁定,又怎麼反饋呢?看官方怎麼說的。。。

下文:

地址:http://developer.xamarin.com/guides/android/under_the_hood/architecture/

英文很差的同窗,本身打開網址找翻譯工具吧。

大概意思是:MCW 的綁定機制還有ACW的核心就是 JNI    

JNI是什麼鬼?科普一下:JNI是Java Native Interface的縮寫,它提供了若干的API實現了Java和其餘語言的通訊(主要是C&C++)。

好,既然提供交互入口JNI,那麼咱們的代碼在通過monodroid處理後,就能夠與Android這個java項目交互了。

那麼C#語言是否是被處理轉換成了JNI的應用了?是的。看圖:

 

看完上圖,你應該知道了,它在編譯的時候,將C#代碼文件,轉化成了基於對Java原生文件的映射。注意:不是直接轉化成了Java代碼!是調用註冊。

生產的java文件中並不提供運行實現,而是提供了在Android運行時的匹配映射!!!!!!!!!!!!!!!

真正的執行代碼依然在classes.dex文件中。但並非咱們的C#編譯的業務代碼哦~~~業務代碼一下子會說的哦(這個文件是二進制的可被安卓虛擬機執行的文件,跟語言無關)。

Java原生的開發會把業務代碼壓縮進此文件。這個文件也是安卓虛擬機執行對應的應用時候,能找到入口,起始點。可是,Mono項目的業務代碼沒在這個裏面,記住,它是皮影戲。這個是皮影。真正的操做者,幕後兇手,在後臺!!!

上法寶:

 

Xamarin生成的apk包中,也是這樣。

lib目錄提供了運行時須要的lib 庫,如Mono運行時。

注意下面的那倆文件,就是皮影戲的杆兒,映射工具。

真正的執行代碼在????

在 lib 中或者在assemblies中!!

爲啥是或者?由於企業版的Xamarin,支持使用NDK將應用打包成Native應用!!!

有的人糾結那個calsses.dex文件,做爲入口,說Android的應用不是非線性耦合的模塊應用嗎?是的,可是,這非線性針對的是系統,或者是程序塊內部,而不是系統跟程序應用之間的描述。應用插入到系統上,那個自描述文件 AndroidManifest.xml 提供了程序的入口描述。

而calsses.dex被安卓虛擬機 Dalvik 執行後,會給這個程序分配對應的程序運行域,

 (摘自:騰飛(Jesse))關於Dalvk虛擬機與Java運行環境的區別

  1. Dalvik主要是完成對象生命週期管理,堆棧管理,線程管理,安全和異常管理,以及垃圾回收等等重要功能。
  2. Dalvik負責進程隔離和線程管理,每個Android應用在底層都會對應一個獨立的Dalvik虛擬機實例,其代碼在虛擬機的解釋下得以執行。
  3. 不一樣於Java虛擬機運行java字節碼,Dalvik虛擬機運行的是其專有的文件格式
  4. Dex文件格式能夠減小總體文件尺寸,提升I/o操做的類查找速度。
  5. 是爲了在運行過程當中進一步提升性能,對dex文件的進一步優化。
  6. 全部的Android應用的線程都對應一個Linux線程,虛擬機於是能夠更多的依賴操做系統的線程調度和管理機制
  7. 有一個特殊的虛擬機進程Zygote,他是虛擬機實例的孵化器。它在系統啓動的時候就會產生,它會完成虛擬機的初始化,庫的加載,預製類庫和初始化的操做。若是系統須要一個新的虛擬機實例,它會迅速複製自身,以最快的數據提供給系統。對於一些只讀的系統庫,全部虛擬機實例都和Zygote共享一塊內存區域。

  你們注意第2點和第7點有助於咱們理解Xamarin.Android的工做機制

 

好,到此,你就知道了吧,那個classes.dex 就是給Zygote提供孵化器應用的............Zygote(受精卵。很形象。應用像是受精卵,經過他暖化出來了個小雞應用)

 

KO!!!!!!!到此,你也就基本知道,這玩意兒是怎麼運行的了吧。。。。沒錯,記住,皮影戲!!!!!!!!!!!!!!!

-----------------------------垃圾回收----------------------------------------

關於這個話題,其實不必過度討論,由於既然是皮影戲,那麼確定兩邊交互的時候 確定不如原生,若是你糾結這個,那麼請學好Java去吧。

而後就是硬件的問題,從09年到如今,內存啊 CPU什麼的再移動終端上換了好幾代了。從單核到雙核到四核到八核。。。。。硬件的提高簡直是要親命的。

花好幾個月優化的項目,可能新一代的的硬件直接藐視了之前的項目性能問題。。。(固然,不能不關注性能。在一些遊戲 視頻等對硬件渲染要求較高的時候,就能體現出性能的致命性!!)

好了看到這裏,你也不必繼續往下看了。下面的是基於Xamarin的內存管理。

由於是皮影戲,兩邊實際上是互相持有對方的信息的。耍皮影的根據皮影反饋的信息,進行下一步如何操做,皮影接到命令,就會在屏幕上顯示對應的動做。。。

摘抄:http://www.cnblogs.com/wintersun/archive/2013/02/28/2937270.html

1. 性能問題。例如垃圾回收,Mono for Android 聲稱支持垃圾回收,但也有須要注意的一些嚴重限制。"GC不完整視圖的進程,可能沒法運行在內存不足時,因爲GC不知道內存不足。"由於這一般須要手動,每當建立一個activity運行垃圾回收或銷燬,以釋放未使用的內存。不然,可能致使內存不足的異常。 我本身也不止一次碰到了這個問題,不得不使用替代方法來解決問題。 

關於內存管理: 
許多Mono for Android被分配對象爲包裝Java對象作爲它們的表明。 這時會發生什麼:每次你分配一個包裝過類型相對應Java類型,就建立兩個對象: 
1). Java對象在Java堆中 
2). Mono代理對象在Mono堆中 
Mono for Android不能確保這兩個對象相互引用後長時間存活。那就是,Mono的垃圾回收引用一個對象,Java端的對象將一直活着,反之亦然。這個代理對象的建立mandroid.exe是工具編譯時完成。 然而,GC是懶惰的,按需運行的集合,而不是簡單地對象超出範圍時候。 那麼這意味着跨虛擬機的垃圾至少比通常更多,這是不可避免的。因此,爲了臨時使用時分配一個大數字對象,顯示釋放那些對象所需的資源是寶貴的。約定的方法使用using關鍵字來new一個object,使用using子句來隱式釋放目標的new object是有必要的。釋放Mono端的包裝的Java-VM收集的對象,從而來防止太多的臨時對象關聯在一塊兒很長時間。

去官方網站了解更多關於Mono for Android的垃圾回收

其實,Mono已經對垃圾回收機制,一直在優化。

針對iOS的MonoTouch目前支持了分代式垃圾回收器(generational garbage collector)SGen。直到不久以前,Sgen還只是完整版本Mono中的一個實驗性部分。伴隨着垃圾回收器一同到來的,還有一個爲iOS準備的 內存分析器(Memory Profiler),它能夠從MonoDevelop集成開發環境中訪問到。

分代式垃圾回收器Sgen取代了Mono中傳統的Boehm垃圾回收器。雖然Sgen預計會有更好的性能,但其保守式掃描仍然會給它帶來一些阻礙。預計未來Sgen會切換到精確的堆棧標記系統,這樣應當能夠大幅度減小產生的內存碎片。

iOS分析器支持兩種模式,默認模式是堆分析模式,在該模式中內存快照能夠根據須要或者觸發器進行採集,而該觸發器能夠設置成必定數量的垃圾收集器週期或者基於時間的時間間隔。此外,該分析器還包含了一些標準工具,如對比快照和查找內存中的對象位置。

性能分析支持統計抽樣,以及精確性雖佳但速度不足的進入/離開事件記錄。統計抽樣採集應用程序快照,並根據每一個方法被採集器抓取的頻度對它們的速度 進行評估。從字面上看,進入/離開事件記錄就是在函數每次開始或完成時記錄一條日誌。它雖然提供了時間花費的完整記錄,但會帶來嚴重的性能開銷。這種模式 一樣可以捕獲與對象分配相關的堆棧跟蹤。

MonoDevelop 2.8.5和MonoTouch 5.1.1都規定使用該工具。而對於個別項目,必須激活調試、分析和SGen垃圾回收器選項。

Sgen 項目一直在推動着。。。

關於怎麼個機制,本身看官方文章吧。太長,不翻譯了。

http://www.mono-project.com/docs/advanced/garbage-collector/sgen/

https://developer.xamarin.com/guides/android/advanced_topics/garbage_collection/

院子裏卻是有點小資料,瞭解下就是了。

來自:http://www.cnblogs.com/shanyou/archive/2012/12/09/2810468.html

Mono 3如今是默認 GC是SGen 垃圾回收器,垃圾回收器幾個性能和擴展性方面的改進,以更好地利用多核處理器硬件。SGen 已移植到 Windows 和 MIPS。

mono 最開始使用的是 Boehm-Demers-Wiser Conservative Garbage Collector ,mono 3.0以前的版本做爲默認的垃圾收集器也是這個,Boehm垃圾收集器的主要問題在於沒法精確讀取寄存器與棧幀。由於沒法肯定給定值究竟是指針仍是標量,所以它老是假設給定值是指針,而且將相關聯的對象標記爲存活狀態。這麼作不只會錯誤致使大塊內存沒法分配,同時還使得壓縮可用空間這項工做變得異常艱難。

後來mono有了本身的 Simple Generational GC , 就是分代式垃圾回收器Sgen,取代了Mono中傳統的 Boehm垃圾回收器。文檔地址:http://www.mono-project.com/Compacting_GC,它使用精確的分代式(generational)垃圾收集器,相似於.NET版本的CLR。SGen垃圾收集器使用兩生代而非.NET中的三個,但像.NET同樣對於大對象使用獨立的堆。

  1. 分爲兩代,以前使用 conservative gc..可見其文檔的描述。是一種較爲落後的實現,沒有分代,.NET 的CLR是三代的
  2. 大對象特殊處理,默認大於64KB做爲大對象,.NET的大對象是20KB以上,被分配到一個特殊的大對象堆中。該堆中的對象像其它小對象同樣能夠被finalized和釋放。
  3. 小對象採用get_internal_mem/free_internal_mem 進行內存分配處理,大對象使用OS的malloc/free
  4. major collection 的時候採用 mark/sweep
  5. 收集進行時是 「stop the world」
  6. 保守掃描對象
  7. 老一代指向新一代的狀況只有下面兩種,因此都進行了跟蹤:
  • 程序執行中,一個字段進行了賦值
  • 在複製(代移動)過程當中,這個對象指向了一個新一代中的對象

Mono 3.2進一步提高了SGen GC,特別是針對下面的場景——

  • 流行對象負載,老一代對象很是歡迎的一些固定新生對象會致使建立不少記憶的集合。爲了不這種狀況的發生,流行對象會被做爲永恆對象直到下一次主收集。
  • 大規模線程棧負載,這種狀況下須要合理地掃描大量大堆棧線程。這在之前一般會把大量壓力放到規劃階段,由於它會產生很是大的固定隊列。爲了不這種狀況,SGen如今會在固定隊列上使用哈希過濾,這大大下降了它們的平均大小,而且它會固定主要塊而不是個別對象。

Mono 3.0添加了異步支持、改進的SGen垃圾收集器及其餘特性

用Xwt構建跨平臺應用程序

new Mono GC

SGen – Concurrent Mark

SGen – Concurrency and Evacuation 

Flame Graphs for Instruments 

How sgen rocks

SGen – The Write Barrier

SGen and DTrace

SGen – Finalization and Weak References

SGen – The Major Collectors

SGen

相關文章
相關標籤/搜索