[你必须知道的.NET]第二十六回:认识元数据和IL(下)

说在,开篇之前
书接上回: 
第二十四回:认识元数据和IL(上), 第二十五回:认识元数据和IL(中) 

我们继续。 

终于到了,说说元数据和IL在JIT编译时的角色了,虽然两个回合的铺垫未免铺张,但是却丝毫不为过,因为只有充分的认知才有足够的体会,技术也是如此。那么,我们就开始沿着方法调用的轨迹,追随元数据和IL在那个神秘瞬间所贡献的力量吧。  

                                                                                      www.anytao.com

 

 

5 元数据和IL在JIT编译时

CLR最终执行的只有本地机器码,所以JIT编译的作用是在运行时将IL代码解析为机器码执行。对于JIT编译,我们会以专门的篇幅来全面了解,本文只将目光关注于元数据和IL在程序执行时的作用和参与细节。首先,IL是基于栈执行的,执行方法调用时,方法参数、局部变量还有返回值等被分配于栈上,并执行其调用过程,既然是关注JIT编译时,因此我们自然而然将关注方法的执行,因为JIT编译是以执行方法调用而触发的。

首先,对本文开始的代码加点新料:

// Release : code04, 2009/02/24                    
// Author  : Anytao, http://www.anytao.com
// List    : Base.cs
public class Base
{public void M(){Console.WriteLine("M in Base");}public virtual void N(){Console.WriteLine("N in Base");}
}

还有:

// Release : code05, 2009/02/24                    
// Author  : Anytao, http://www.anytao.com
// List    : Three.cs
public class Three : Base
{private static int ID { get; set; }public override void N(){//Something new in ThreeConsole.WriteLine("N in Three");}public void M(){Console.WriteLine("M in Three");M1();}public void M1(){Console.WriteLine("M1 in Three");}
}

还有执行代码:

static void Main(string[] args)
{Base three = new Three();three.M();three.N();
}

小窥方法表

以该例而言,执行Main方法调用时,同时伴随着对于Three实例的创建,和相应类型信息的加载。我们先将类型信息创建的秘密放在以后的内容中,好留点悬念在未来发挥,哈哈。然而,类型加载一定是在实例创建之前完成的,也就是我们常常提起的方法表创建。类型加载是由class loader负责执行的,其过程简言之就是从元数据表中获取相应的类型信息,创建方法表(包含CORINFO_CLASS_STRUCT结构),其结构主要包括非虚方法表和虚方法表,按照继承的虚方法、新引入的虚方法、实例方法和静态方法的顺序排列,以类Three类型为例其CORINFO_CLASS_STRUCT结构可以表示为:

Note: 在本例中Three没有定义任何静态方法,其方法表中父类方法N已有子类覆写,同时因为有静态成员存在的原因,CLR会自动创建类型构造器,详细情况可参考《你必须知道的.NET》1.2节 “什么是继承”。

我们可以同过加载SOS调试来了解相应的方法表信息:

  • 在three.N()调用处打好断点,来查看该时刻的dump信息,就像一个内存快照,发现多少东西就看摄影师的水准。
  • 然后,通过dumpheap加载类型信息,获取方法表地址(0x002a354c),
!dumpheap -type Three
Address       MT     Size
01d332c4 002a354c       12     
total 1 objects
Statistics:MT    Count    TotalSize Class Name
002a354c        1           12 Anytao.Insidenet.MetadataIL.Three
  • 并根据MT地址,以dumpmt查看相关的MethodDesc信息,
!dumpmt -md 002a354c
EEClass: 002a15b4
Module: 002a2f2c
Name: Anytao.Insidenet.MetadataIL.Three
mdToken: 02000003  (E:\anytao\Today\OnWriting\MetadataIL\Anytao.Insidenet.MetadataIL\Anytao.Insidenet.MetadataIL\bin\Debug\Anytao.Insidenet.MetadataIL.exe)
BaseSize: 0xc
ComponentSize: 0x0
Number of IFaces in IFaceMap: 0
Slots in VTable: 10
--------------------------------------
MethodDesc TableEntry MethodDesc      JIT Name
6f756a70   6f5d1328   PreJIT System.Object.ToString()
6f756a90   6f5d1330   PreJIT System.Object.Equals(System.Object)
6f756b00   6f5d1360   PreJIT System.Object.GetHashCode()
6f7c7460   6f5d1384   PreJIT System.Object.Finalize()
002ac0b8   002a3514     NONE Anytao.Insidenet.MetadataIL.Three.N()
002ac0d0   002a3540      JIT Anytao.Insidenet.MetadataIL.Three..ctor()
002ac0a8   002a34f4     NONE Anytao.Insidenet.MetadataIL.Three.get_ID()
002ac0b0   002a3504     NONE Anytao.Insidenet.MetadataIL.Three.set_ID(Int32)
002ac0c0   002a3520     NONE Anytao.Insidenet.MetadataIL.Three.M()
002ac0c8   002a3530     NONE Anytao.Insidenet.MetadataIL.Three.M1()

经过简单的Dump,方法表的信息和我们图示的信息相差无几,细心的观众可能会发现Dump信息中并不包含Three::cctor(),那么你答对了。图示的cctor是我基于为Three实现了类型构造器(静态构造函数)而特别加入的,而代码中dump的方法表并没有把类型构造器包含在内,这是个小粗心,希望细心的您看得够透。

执行细则

具体的执行过程为为:

  • class loader从TypeDef元数据表加载相关元数据信息,包括当前类型,继承层次的所有父类和实现的接口元数据,根据这些信息建立CORINFO_CLASS_STRUCT结构:

当然,对class loader,我们可以进行一点知识救急:

 

上课啦:class loader

Classic Loader是CLR提供的基本组件之一,作用正像其名称所宣扬的那样,load一个Class给CLR,class loader将Metadata和IL从PE文件中取出,并加载到运行时内存,简单的说就是我们下面要介绍的全过程缩影。

当然,如果你总是对CLR的Classic Loader耿耿于怀,不能释然。那么,我们也可以参考MSDN的资料来实现自定义的Classic Loader[How to: Write a Class Loader],希望其中能提供灵光一现的思考。

                                                                                      www.anytao.com

 

  • 加载之后,方法执行之前的CORINFO_CLASS_STRUCT中所有的方法表槽都保存了方法应该执行的行为逻辑,这些信息保存在被称为方法描述(MethodsDesc)的结构中,而MethodDesc则被初始化为指向IL代码,同时还包含一个指向触发JIT编译的PreJitStub地址,如下:

上述所有方法描述都指向各自的IL代码地址和JIT编译器,在此我们仅仅以N()方法为例来进行说明,详细的情况可以参考MSDN相关内容。

  • 简单的说,任何方法第一次执行时都会首先触发执行JIT编译,JIT的主要工作就是将IL代码翻译为Native Code,并插入指向Native Code的jmp指令地址覆盖原来的Call JIT Compiler指令:

  • 当该方法再次被执行时,因为MethodDesc中保存了机器码地址,以后的执行将不会执行JIT编译过程而直接执行x86(X64)机器码,实现整个执行过程。

纵观整个JIT编译的全过程,其细节的实现远比我们这里呈现的复杂,在粗略的步骤中我们大致了解了元数据和IL在整个过程中的作用、角色和关系,对了解CLR运行机制而言,适当的选择是明智的,如果有更多的心思探索,那么就在以后的岁月中由简及繁吧,但是相信这一定是一次美妙的旅程。

6 结论

Metadata描述了静态的结构,而IL阐释了动态的执行,这一静一动承载了太多的技术奥秘。

当这篇文章行将结束的时候,我发现牵一发而动全身,由此引入的新问题接踵而至,方法调用、程序集、程序域、CLR加载过程在元数据和IL的分析中若隐若现,也驱使我投入注意在后面的《你必须知道的.NET》中,将这些内容一一过招。由此才能在复杂的概念和本质之余,由点及面的对所有内容综合把握,形成全面的了解和一条线贯穿的认识,那么未来Anytao将要继续分享还有:

系列预告
  • 程序集和模块
  • 程序域
  • CLR加载过程
  • JIT编译
  • 方法调用
  • 反射种种
  • 其他…

                                                                                      www.anytao.com

限于繁忙的原因,我无法给出一个清晰的时间表,但力图每次的内容都给您出足够的收获,如果你对.NET始终心怀兴致,那么敬请期待《你必须知道的.NET》更多精彩。 


支持anytao的创业产品Worktile
Worktile,新一代简单好用、体验极致的团队协同、项目管理工具,让你和你的团队随时随地一起工作。完全免费,现在就去了解一下吧。
https://worktile.com

  • 《你必须知道的.NET》第3章 “一切从IL开始”
  • DonBox,《.NET本质论》
  • http://www.sloppycode.net/articles/inside-net-assemblies-and-metadata.aspx
  • http://www.codeproject.com/KB/dotnet/dotnetformat.aspx

温故知新

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/438705.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机电子电路原理图,学看电路原理图入门知识积累 - 全文

一、电子电路的意义电路图是人们为了研究和工程的需要,用约定的符号绘制的一种表示电路结构的图形。通过电路图可以知道实际电路的情况。这样,我们在分析电路时,就不必把实物翻来覆去地琢磨,而只要拿着一张图纸就可以了。在设计电…

[你必须知道的.NET]第二十八回:说说Name这回事儿

1 缘起 老赵在谈表达式树的缓存(2):由表达式树生成字符串中提到,在描述Type信息时讨论FullName或者AssemblyQualifiedName提供完整的Type信息,虽是小话题,但却是值得有聊的话题。在.NET中反应一个Type名称…

library的英语怎么读音_【英语角】———学习方法分享

点击蓝字 关注我们每天学习一点点单词的记忆是一件很让人头疼的事情,但单词又是学习英语的基石,非常重要。那么有什么方法能让单词记忆变得简单有效呢?不妨试试下面这些方法吧。1、卡片记忆自制单词卡片,随身带着,有空…

计算机作文叙事,电脑争夺战叙事作文

电脑争夺战叙事作文在生活、工作和学习中,大家一定都接触过作文吧,作文是通过文字来表达一个主题意义的记叙方法。那么你有了解过作文吗?下面是小编帮大家整理的电脑争夺战叙事作文,欢迎阅读与收藏。这是一个温暖的下午&#xff0…

[你必须知道的.NET]第二十九回:.NET十年(上)

引言 语言是程序开发者行走江湖的手上利器,各大门派的高手在论坛、博客为了自家门派争吵不已早是技术世界中的亮丽风景,虽多少为刚刚踏入江湖的新手提供了思考的素材,但也同时迷惑了初出茅庐的前行方向。 本文不欲计较门派的高下&#xff0…

springboot 做表白墙_华广表白墙 第六期|hsl每天都想和你嘻嘻哈哈

1回复第五期 10 没了就没了,不值得就要留恋219级人力4班的银发女生看见你的第一眼就觉得你是一个天使,你的眼睛真的把我迷住了。如果可以的话能不能加你的微信,谢谢?3捞一下13号(周日晚上)21.15左右在校门口益禾堂买奶茶的小姐姐 金发 牛仔…

51系列计算机字长,计算机等级考试之MsOffice练习题第51套

为了让广大各位考生更好的复习,帮考网小编整理提供了2012计算机等级考试一级MsOffice精选题(51),以供各位考生复习参考,希望对考生复习有所帮助。/计算机二级2012计算机等级考试一级MsOffice精选题(51)1)。 正确的IP地址是A) 202.112.111.1B)…

navcat定时备份mysql_Linux实现MYSQl数据库的定时备份

今天给大家分享一下如何在Linux下实现MYSQl数据库的定时备份。前提需要保证你的Linux服务器已经安装了MYSQl数据库服务。1、创建shell脚本vim backupdb.sh创建脚本内容如下:#!/bin/shdb_user"root"db_passwd"123456"db_name"userdb"n…

[你必须知道的.NET]第三十一回,深入.NET 4.0之,从“新”展望

总体来说,这是一篇介绍性的文章,不会涉及过多技术细节和研究过程。但是,作为拉开序幕的第一页,本文以提纲挈领的方式展开对.NET 4.0的初次体验。从What’s new的角度,开始我对.NET 4.0新特性的探索之旅。既然是介绍&am…

苹果计算机磁盘格式,Mac怎么将ntfs格式的磁盘格式化

1. 首先下载NTFS For Mac。下载之后就可以读取NTFS磁盘。2. 插入要格式化的NTFS磁盘。您可以在Mac OS X下通过命令行格式化NTFS磁盘。按照以下步骤进行操作:启动命令行:应用程序 》 工具 》 终端; 输入diskutil获取帮助。格式化命令图:使用di…

[你必须知道的.NET]第三十二回,,深入.NET 4.0之,Tuple一二

Tuple,是函数式编程的概念之一,早见于Elang、F#等动态语言。不过,我第一次听说Tuple还早在2005年园子的Ninputer大牛提出在.NET 2.0实现Tuple的基本想法,我们可以通过以下地址仰慕当时的历史片段: 探讨.NET 2.0中Tuple…

支持商用吗_可商用的插画素材 | 美翻了

好素材在手,天下我有啊...哈哈哈喽大家周末好,那上周公子做的那份工作型插画模板呢,很多小伙伴都来问我素材是哪里找的,自己画的吗当然不是了!其实我在文章中已经提到了,那有的人可能之前用过或可以自己找到…

永恒边境白羊座服务器维护,永恒边境升级攻略 速升50级技巧

永恒边境怎么升级快?分享永恒边境升级攻略,下面我们就一起来看看永恒边境速刷主线支线任务技巧,希望对大家有所帮助。20-30级篇在这个阶段,我们就主线任务和支线任务大家都不要错过了,都要好好抓住,我还可以…

格式化css文件,css文件格式化脚本的方法

这次给大家带来css文件格式化脚本的方法,css文件格式化脚本的注意事项有哪些,下面就是实战案例,一起来看一下。#!/usr/bin/python# -*- coding: UTF-8 -*-import sys,osdef format(ddt):ddt ddt.replace(\n,)#去除换行ddtddt.replace(;},}).…

[你必须知道的.NET]第三十四回,object成员,不见了!

在.NET世界了,object是公认的造物主,其麾下的7大成员,个顶个的横行在任何系统的任何代码角落。 public class Object {public Object();public virtual bool Equals(object obj);public static bool Equals(object objA, object objB);publi…

直接请求接口_http类型的post和get接口测试

我们做接口测试时候,会发现通常需要测试的接口类型有好几种,比较多的是http类型的接口,其他还有webservice接口,rpc接口等等,本次主要说下http类型的接口我们该怎么测试,还有该测试哪些东西。HTTP接口概念:…

css3加载中动画效果,CSS3实现加载中的动画效果

Loading 的菊花图形组合的不太好,基本上实现这个功能了动画解析这个动画用到的 CSS3 特性:transform 主要使用 transform 属性的 rotate,将线条组合成 Loading 图形 (也就是常见的菊花图形)animation 实现将线条颜色由浅到深,再由深到浅来回变…

[你必须知道的.NET]第三十五回,判断dll是debug还是release,这是个问题

问题的提出 晚上翻着群里的聊天,发现一个有趣的问题:如何通过编码方式来判断一个dll或者exe为debug build还是release build?由于没有太多的讨论,所以我只好自己找点儿办法,试图解决这个问题,为夜生活带点…

执行本地sql_实用!5个在线 SQL 数据库环境

文章目录SQL FiddleDB Fiddledb<>fiddleSQL OnlineOracle Live SQL总结大今天给大家分享几个在线的免费 SQL 运行环境&#xff0c;也就是在线数据库。这些网站可以帮助我们快速运行一些 SQL 语句的测试或者验证&#xff0c;同时还可以在网络上进行分享&#xff0c;关键不…

ocp证书怎么考_没有基础怎么考初级会计证书?

初级会计证书这些年来越发火热&#xff0c;报考门槛也较低。多数报考初级会计证的考生都是没有基础的&#xff0c;那么怎么复习呢?今天会计网将给大家带来没有基础怎么考初级会计证书?1、制定一份适合自己的学习计划&#xff0c;分阶段学习对于没有基础的考生而言&#xff0c…