2.1 Mono是什么
Mono是一个由Xamarin公司所赞助的开源项目。它基于通用语言架构(Common Language Infrastructure,缩写为CLI)和C#的ECMA标准(Ecma-334、Ecam-335),提供了微软的.NET框架的另一种实现。与微软的.NET框架不同的是,Mono具备了跨平台的能力,也就是说它不仅能运行在Windows操作系统上,而且还可以运行在Mac OSX、Linux操作系统上,甚至是一些游戏平台上。
自从2004年发布Mono 1.0版本以来,Mono也逐渐从Linux桌面应用程序开发者平台发展成为了支持广泛的硬件架构和操作系统的平台。
而作为微软的.NET框架在不同平台上的重要补充,Mono也被很多公司所采用,这其中就包括Unity 3D的开发者——Unity Technologies公司。他们为Unity 3D引入了Mono,以帮助游戏开发者获取开发跨平台游戏的能力。
2.1.1 Mono的组成
从剖析Mono的组件来看看它是如何组成的。Mono的组件主要可以分为以下几个部分。
• C#编译器。目前最新的Mono版本(v4.0.1)的C#编译器完全兼容C#1.0、2.0、3.0、4.0以及5.0。但是由于一些历史原因,Unity 3D采用的Mono版本仍然停留在2.0+的阶段。所以C#的一些新功能,在Unity 3D中是不会出现的。而在Mono的发展历史上,同样的编译器却有很多不同的版本。例如gmcs(编译目标为2.0 mscorlib)、smcs(编译目标为2.1 mscorlib,主要用来构建MoonLight应用)、dmcs(编译目标为4.0 mscorlib)。而Mono从Mono 2.11版本开始,采用了一个统一的编译器——mcs。它的出现替代了之前提到过的3种编译器的不同版本。而由于mcs是C#写的编译器,而且还使用了很多.NET的API,所以在非Windows平台上需要Mono运行时(Runtime)来运行mcs。而在Windows平台上,既可以使用微软的.NET运行时,也可以使用Mono运行时。
• Mono运行时。运行时实现了前面提到过的Ecma的通用语言架构标准,该标准是一个开放的技术规范,它定义了构成.NET框架基础结构的可执行代码,以及代码的运行时环境,也就是说该标准旨在定义一个与具体语言无关的、跨架构系统的运行环境。具体而言,Mono运行时提供了一个即时编译器(Just-in-time,缩写为JIT),以及一个提前编译器(Ahead-of-time compiler,缩写为AOT)。同时还有类库加载器、垃圾回收器和线程系统等。
• 基础类库。Mono平台提供了广泛的基础类,为构建应用提供一个坚实的基础,而这些类库也同微软的.NET框架兼容。
• Mono类库。Mono也提供了很多超越基础类库、超越微软的.NET框架的类。这些类提供了很多有用的额外功能,特别是在构建Linux的应用方面。例如一些处理Gtk+、Zip files、LDAP、OpenGL、Cairo、POSIX的类。
2.1.2 Mono运行时
在刚刚介绍的Mono组件中,提到了C#编译器——mcs。而mcs的作用是将C#编译为ECMA CIL的byte code,之后则需要Mono运行时中的编译器,将CIL的byte code再转译为原生码(Native Code,即本地CPV的图标执行代码)。Mono运行时为我们提供了2种编译器和3种转译方式。3种转译方式如下。
• 即时编译(Just-in-time,JIT):在程序运行的过程中,将CIL的byte code转译为目标平台的原生码。
• 提前编译(Ahead-of-time,AOT):在程序运行之前,将.exe或.dll文件中的CIL的byte code转译为目标平台的原生码并且存储起来。但仍会有一部分CIL的byte code会在程序运行的过程中进行转译,即有一部分转译工作仍需要JIT编译。
• 完全静态编译(Full-ahead-of-time,Full-AOT):这种模式出现的目的,是完全杜绝在程序运行的过程中使用JIT编译。也就是说在程序运行之前,所有的代码已经被编译成了目标平台的原生码。在Unity 3D开发中,最典型的平台就是iOS平台。
而Mono运行时提供的另一个重要的功能便是垃圾回收器(garbage collection,缩写GC)。由于使用了垃圾回收机制,所以就避免了开发人员手动管理内存所带来的风险,无须开发人员去告诉运行时环境究竟应该何时收回某个对象的空间,取而代之的是运行时会追踪目标对象,并且自行决定是否回收对象的内存。不过与微软.NET框架不同,在Mono 2.8版本发布的前后,它有两套不同的垃圾回收机制——分代收集(generational collector)以及贝姆垃圾收集器(Boehm-Demers-Weiser garbage collector)。而Mono早期所采用的贝姆垃圾收集器与.NET框架的垃圾回收器相比一直有很大的限制,在某些状况的应用软件上会发生内存泄漏的现象,由于Unity 3D使用的并非微软的.NET框架,而是开源的Mono,更具体地说是Mono比较早期的版本,所以Unity 3D的垃圾回收性能并不如.NET的垃圾回收性能。