共享程序集和强命名程序集(4):“运行时”如何解析类型引用

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 Program
11     {
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: <null>
    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

时间: 2024-10-31 22:23:32

共享程序集和强命名程序集(4):“运行时”如何解析类型引用的相关文章

03.共享程序集和强命名程序集

进行私有部署时,程序集放在应用程序的基目录(或者它的一个子目录)中的,这个应用程序专用的.以私有方式部署程序集,可以对程序集的命名.版本和行为进行全面的控制 CLR支持两种程序集,一种是弱命名程序集,一种是强命名程序集 强命名程序集使用发布者的公钥/私钥对进行签名,它唯一性地标识了程序集的发布者 弱命名程序集只能进行私有部署,"全局部署的程序集"是部署到一些已知的位置的程序集 强命名程序集 具有4个重要的attributes,它们共同对程序集进行唯一性标识:一个文件名.一个语言文化,一

学习 第三章CLR共享程序集和强命名程序集

CLR 支持两种程序集:弱命名程序集(weakly named assembly)和强命名程序集(strongly named assembly) 程序集可采用两种方式部署:私有和全局 弱命名程序集只能以私有方式部署 强命名程序集部署即可私有又全局. 强命名程序集具有4个重要特性:文件名(不计扩展名),版本号,语言文化,公钥 例如:"MyTypes,Vesion=1.0.8123.0,Culture=neutral,PublicKeyToken=b77a5c561934e89" 注意:

第三章 共享程序集和强命名程序集

1. 概述 本章的重点是如何创建可由多个应用程序访问的程序集. 2. 名词解释 ① 公钥标记:从公钥派生的一个小的哈希值. 3. 主要内容 3.1 两种程序集,两种部署   CLR支持两种程序集:弱命名程序集 和 强命名程序集. 一个程序集可以采取两种方式来部署:私有 或 全局. 弱命名程序集只能私有部署,强命名程序集两种部署皆可. 3.2 为程序集分配强名称 强命名程序集具有四个重要组成部分: ① 一个文件名 ② 一个版本号 ③ 一个语言文化标识 ④ 一个公钥(一般用 公钥标记). 用SN.e

共享程序集和强命名程序集(下)

1.1   强命名程序集能防篡改 1.2   延迟签名. 1.3   私有部署强命名程序集 1.4   "运行时"如何解析类型引用 1.5   高级管理控制(配置) 原文地址:https://www.cnblogs.com/lzcgis/p/10251725.html

共享程序集和强命名程序集(上)

1.1   两种程序集,两种部署(待更新...) 两种程序集:弱命名程序集,强命名程序集.两者结构完全相同.区别:强命名程序集使用发布者的公钥/私钥进行签名. 部署:私有或者全局. 1.2   为程序集分配强名称 1.3   全局程序集缓存 1.4   在生成的程序集中引用强命名程序集 原文地址:https://www.cnblogs.com/lzcgis/p/10251718.html

强命名程序集,签名,延迟签名

强命名程序集 如果一个程序集有一个唯一的标记,那么这个程序集就可以叫做强命名程序集.在.NET框架中是通过公钥/私钥加密来产生这个唯一标记的.一个强命名程序集包含四个唯一标志程序集的特性:文件名(没有扩展名),版本号,语言文化信息(如果有的话),公有秘钥. 这些信息存储在程序集的清单(manifest)中.清单包含了程序集的元数据,并嵌入在程序集的某个文件中.下面的字符串标识了二个不同的程序集文件: “MyType, Version=1.0.1.0,Culture=neutral, Public

CLR 关于强命名程序集 .

如何创建强命名程序集(Strong Name Assembly)     创建一个强命名程序集首先需要获得一个用强命名实用工具   (Strong Name Utility,即SN.exe,.NET SDK自带)产生的密钥.   下面简要介绍一下SN.exe的一些用法. 要产生一个公钥/私钥对:     a)SN –k MyCompany.Keys   该命名告诉SN.exe创建一个名为MyCompany.keys的文件.MyCompany.keys文件将包含以对以二进制格式存储的公有密钥和私有

使用强命名程序集防范篡改

CLR支持两种程序集:强命名程序集.弱命名程序集,两者的区别在于,强命名程序集是被发布者使用了自己的公钥/私钥对进行了程序集的签名,能唯一性标识程序集的发布者的程序集,并且可以使用密钥对程序集进行唯一性标识.保护和版本控制,这里所提到的保护就是我们需要一起讨论的程序集防篡改. 首先我们一起来看个例子,这样能简单明了地说明使用强命名程序集的必要性. 我们建立一个WinForm程序Nick.WinFormApp,添加一个登录窗体,并且在此项目内引用名为Nick.AuthProvider的程序集,用于

强命名程序集组成与作用

强命名 由一个程序集的标识组成并通过公钥和数字签名(针对该程序集生成)加强的名称,其中的标识包括程序集的简单文本名称.版本号和区域性信息(如果提供的话). CLR需要支持某种机制来唯一的标识一个程序集.这就是所谓的强命名程序集..Net使用Name.Version.Culture.PublicToken四个属性来唯一标识一个程序集.强命名程序集正是使用RSA(非对称算法)生成的公钥/私钥来保证public Token的唯一性,.net在编译项目时将指定的公钥/私钥写入程序集来保证其唯一性.