不知接口方法和虚方法分发有什么区别?似乎在CIL中都是callvirt指令。

对,MSIL里都是callvirt,但JIT的时候得到了不同的处理:
对虚方法的分发是编译成这样:

  1. mov  ecx, esi              ; 假设现在ESI是一个指向对象实例的指针,复制到ECX里
  2. mov  eax, dword ptr [ecx]  ; 对象实例的第一项是指向方法表的指针,复制到EAX里
  3. call dword ptr [eax + 7Ch] ; EAX现在指向方法表,0x7C是我随便写的一个偏移量。这个在加载类的时候就可以确定
mov  ecx, esi              ; 假设现在ESI是一个指向对象实例的指针,复制到ECX里
mov eax, dword ptr [ecx] ; 对象实例的第一项是指向方法表的指针,复制到EAX里
call dword ptr [eax + 7Ch] ; EAX现在指向方法表,0x7C是我随便写的一个偏移量。这个在加载类的时候就可以确定

对接口方法的分发是编译成:

  1. mov  ecx, esi             ; 跟上面一样,ESI是指向对象的指针,复制到ECX
  2. call dword ptr [0099EEA0h] ; JIT的时候指向一个固定地址的stub(这里数字是随便编的,别在意)
mov  ecx, esi             ; 跟上面一样,ESI是指向对象的指针,复制到ECX
call dword ptr [0099EEA0h] ; JIT的时候指向一个固定地址的stub(这里数字是随便编的,别在意)

这个call是对一个固定地址做间接调用。一开始是调用到一个通用的resolver stub,去找具体的方法的地址。如果在同一个调用点出现两次相同类型的被调用对象,则间接调用会指向为该类型特化的一个dispatch stub上,样子类似这样:

  1. cmp dword ptr [ecx], 009A3377h ; 后面的常量是特定类型的方法表地址
  2. jne 0091A012                   ; 比较不相等的话,跳转到一个特定的resolver stub上
  3. jmp 00EBD070                   ; 相等的话则直接跳转到目标方法的地址
cmp dword ptr [ecx], 009A3377h ; 后面的常量是特定类型的方法表地址
jne 0091A012 ; 比较不相等的话,跳转到一个特定的resolver stub上
jmp 00EBD070 ; 相等的话则直接跳转到目标方法的地址

这段代码被称为monomorphic inline method cache,怎么翻译好呢……单态内联方法缓存? 比较失败时会跳转到一个resolver stub;它会维护一个“不命中计数器”。如果在某个调用点累计失败了100次,就会再次更新之前的间接调用为直接指向通用的resolver stub。
这样,如果在一个接口方法的调用点上总是同一个类型的实例被调用,则分发效率跟虚方法调用差不多快。如果被调用对象的类型经常变,速度就会慢下来了……

CLR 虚方法调用和接口方法调用的更多相关文章

  1. 30分钟入门Java8之默认方法和静态接口方法

    30分钟入门Java8之默认方法和静态接口方法 前言 上一篇文章30分钟入门Java8之lambda表达式,我们学习了lambda表达式.现在继续Java8新语言特性的学习,今天,我们要学习的是默认方 ...

  2. Java8之默认方法和静态接口方法

    前言 上一篇文章30分钟入门Java8之lambda表达式,我们学习了lambda表达式.现在继续Java8新语言特性的学习,今天,我们要学习的是默认方法和静态接口方法. 这一Java8的新语言特性, ...

  3. Java调用webservice接口方法

                             java调用webservice接口   webservice的 发布一般都是使用WSDL(web service descriptive langu ...

  4. 关于使用axis调用webservice接口方法

    1.概述: 我们有时候会调用webserviec接口,我们向接口发送请求参数,从接口接收返回值. 2.形式: package client; import org.apache.axis.client ...

  5. Java调用webservice接口方法(SOAP message、xfire、axis)

    webservice的 发布一般都是使用WSDL(web service descriptive language)文件的样式来发布的,在WSDL文件里面,包含这个webservice暴露在外面可供使 ...

  6. 三种方法实现调用Restful接口

    1.基本介绍 Restful接口的调用,前端一般使用ajax调用,后端可以使用的方法比较多, 本次介绍三种: 1.HttpURLConnection实现 2.HttpClient实现 3.Spring ...

  7. HTTP调用接口方法

    1.创建接口调用方法类 package cn.com.victorysoft.sjzx.Message; import java.io.BufferedReader; import java.io.I ...

  8. JNI-Thread中start方法的调用与run方法的回调分析

    前言 在java编程中,线程Thread是我们经常使用的类.那么创建一个Thread的本质究竟是什么,本文就此问题作一个探索. 内容主要分为以下几个部分 1.JNI机制的使用 2.Thread创建线程 ...

  9. Java调用第三方接口工具类(json、form)

    1.JSON值访问 /** * 调用对方接口方法 * @param path 对方或第三方提供的路径 * @param data 向对方或第三方发送的数据,大多数情况下给对方发送JSON数据让对方解析 ...

随机推荐

  1. Manifold learning 流形学习

    Machine Learning 虽然名字里带了 Learning 一个词,让人乍一看觉得和 Intelligence 相比不过是换了个说法而已,然而事实上这里的 Learning 的意义要朴素得多. ...

  2. tcp关闭连接:挥手讨论

    讨论焦点: 如果client发送FIN后,服务器端未返回完成的数据(缓存区中)还执行返回吗? 参考文档:https://download.csdn.net/download/u013547552/10 ...

  3. EditText编辑框

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...

  4. 惊呆!Java程序员等级一览

      凡人:买本书凑凑热闹,听得多写的少,过段时间就把老师教的都忘了.这个阶段是刷掉人最多的阶段,也是从凡人到程序员本质区别的阶段.你的日后成就在于你的习惯与态度.隔一段时间整理自己的知识体系是重中之重 ...

  5. Web Api 创建及其使用

    由于创建博客,我需要尝试一些新的技术,新的思路,所以我没规规矩矩的写博客,用上了诸多以前没用的东西,比如现在这个(我只是听过web api 我连 web server 都只是用过两三次/手动滑稽) 昨 ...

  6. 用js刷剑指offer(数值的整数次方)

    题目描述 给定一个double类型的浮点数base和int类型的整数exponent.求base的exponent次方. 保证base和exponent不同时为0 牛客网链接 思路 快速幂算法,举个例 ...

  7. spark not serializable异常分析及解决方案

    转载自: http://bigdataer.net/?p=569 1.背景 在使用spark开发分布式数据计算作业过程中或多或少会遇到如下的错误: Serialization stack: objec ...

  8. python中使用uwsgi启动wsgi应用

    uwsgi --http :8000 --wsgi-file wxhttpapi2.py --callable application --processes 4 --threads 2

  9. Python多线程应用于自动化测试

    Python多线程应用于自动化测试 将多线程在测试巧妙地应用,确实会带来很多好处,并且这是充分利用机器资源执行高效率测试很好的方式 # -*- coding: utf-8 -*- import thr ...

  10. Java常用数学类和BigDecimal

    笔记: Math类 * java.lang.Math提供了一系列静态方法用于科学计算:其方法的参数和返回值类型一般为double型. * abs 绝对值 * acos,asin,atan,cos,si ...