博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
共享程序集和强命名程序集(4):“运行时”如何解析类型引用
阅读量:6004 次
发布时间:2019-06-20

本文共 2476 字,大约阅读时间需要 8 分钟。

GAC(Global Assembly Cache) 全局程序集缓存

安装公共语言运行库的每台计算机都有一个称为全局程序集缓存的机器级代码缓存。全局程序集缓存存储专门指定由计算机上的多个应用程序共享的程序集。

“运行时”如何解析类型引用

首先是一组毫无营养但是有用的代码:

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Reflection; 5 using System.Text; 6 using System.Threading.Tasks; 7  8 namespace Project_1 9 {10     public class Program11     {12         public static void Main(string[] args)13         {14             System.Console.WriteLine("HaHa");15        }16     }17 }

 

编译这些代码并生成程序集Program.exe。运行应用程序,CLR会加载并初始化自身,读取程序集的CLR头,查找标识了应用程序的入口方法main的MethodDefToken,检索MethodDef元数据表找到方法的IL代码在文件中的偏移量,将IL代码Jit编译成本机代码,最后执行本机代码。

.method public hidebysig static void  Main(string[] args) cil managed// SIG: 00 01 01 1D 0E{  .entrypoint  // 方法在 RVA 0x2050 处开始  // 代码大小       13 (0xd)  .maxstack  8  IL_0000:  /* 00   |                  */ nop  IL_0001:  /* 72   | (70)000001       */ ldstr      "HaHa"  IL_0006:  /* 28   | (0A)000003       */ call       void [mscorlib]System.Console::WriteLine(string)  IL_000b:  /* 00   |                  */ nop  IL_000c:  /* 2A   |                  */ ret} // end of method Program::Main

 

对这些代码进行JIT编译,CLR会检测所有类型和成员引用,加载他们的定义程序集。上述IL代码包含读System.Console.WriteLine的引用。具体地说,IL call指令引用了元数据token0A000003。该token标识MemberRef元数据表中的记录项3。CLR检查该MemberRef记录项,发现他的字段引用了TypeRef表中的记录项。按照TypeRef记录项,CLR被引到至一个AssemblyRef记录项:

AssemblyRef #1 (23000001)-------------------------------------------------------    Token: 0x23000001    Public Key or Token: b7 7a 5c 56 19 34 e0 89     Name: mscorlib    Version: 4.0.0.0    Major Version: 0x00000004    Minor Version: 0x00000000    Build Number: 0x00000000    Revision Number: 0x00000000    Locale: 
HashValue Blob: Flags: [none] (00000000)

 

这时CLR就知道了他需要的是哪个程序集。接下来,CLR必须定位该程序集。

解析引用的类型时,CLR可能在以下三个地方找到类型:

 ●相同文件:编译时便能发现对相同文件中的类型的访问,这称为早起绑定。类型直接从文件中加载,执行继续;

 ●不同文件,相同程序集:“运行时”确保被引用的文件在当前程序集元数据的FileDef表中,检查假造程序集清单文件的目录,加载被引用的文件。检查哈希值以确保文件完整性。发现类型的成员,执行继续;

 ●不同文件,不同程序集:如果引用的类型在其他程序集文件中,“运行时”会加载被引用程序集的清单文件。如果需要的类型不在该文件中,就继续加载包含了类型的文件。发现该类型的成员,执行继续。

 解析类型引用时有任何错误都会抛出异常。

在上例中,CLR发现System.Console在和调用者不同的程序集中实现。所以,CLR必须查找到那个程序集,加载包含应用程序集的PE文件。然后扫描清单,判断是哪个PE文件实现了类型。如果被引用的类型就在清单文件中,一切都很简单。如果类型在程序集的另一个数据结构来表示类型,JIT编译器完成Main方法的编译。最后,Main方法开始执行。绑定过程如下图所示:

还要注意的是,对于CLR,所有程序集都根据名称、版本、语言文化和公钥来识别。但GAC根据名称、版本、语言文化、公钥和CPU架构来识别。在GAC中搜索程序集时,CLR判断应用程序当前在什么类型的进程中运行,是32位x64,64位x64,还是32位ARM。然后,在GAC中搜索程序集时,CLR首先搜索程序集的CPU架构专用版本。如果没有找到符合要求的,就搜索不区分CPU的版本。

转载于:https://www.cnblogs.com/renzhoushan/p/10397572.html

你可能感兴趣的文章
Matlab2012a下配置LibSVM—3.18
查看>>
Java生成-zipf分布的数据集(自定义倾斜度,用作spark data skew测试)
查看>>
修复CefSharp浏览器组件中文输入Bug
查看>>
正则与sed,grep,awk三剑客
查看>>
诊断一句SQL不走索引的原因
查看>>
iOS开发拓展篇—UIDynamic(简单介绍)
查看>>
Linux pipe函数
查看>>
图片标注工具LabelImg使用教程
查看>>
(原創) 如何設計一個數位相框? (SOC) (Quartus II) (SOPC Builder) (Nios II) (TRDB-LTM) (DE2-70)...
查看>>
/etc/profile文件内容
查看>>
量词 匹配优先与忽略优先
查看>>
一页纸IT项目管理:大道至简的实用管理沟通工具
查看>>
汽车知识:车内异味的清除方法
查看>>
IE6 7下绝对定位引发浮动元素神秘消失
查看>>
android - ADT本地配置、sdk配置
查看>>
I.MX6 dhcpcd 需要指定网卡
查看>>
js递归原理之return
查看>>
浏览器的回流和重绘及其优化方式
查看>>
gulp+browser-sync实现前端自动化刷新
查看>>
python学习笔记 --- 来看看 random_state 这个参数
查看>>