.NET CLR方法表结构

11

我目前正在阅读名为《Pro .NET Performance》的书籍。其中一个章节包含有关引用类型内部结构的详细信息。方法表是引用类型布局结构的一种内部字段。据该书介绍,方法表包含有关类的所有方法的信息。我正在尝试使用一个小程序来验证这个理论。

class MyClass
{
    public void M()
    {
    }
}

static void Main(string[] args)
{
     MyClass m = new MyClass();
     m.M();
     Console.ReadLine();
}  

我使用WinDbg启动这个程序 我的WinDbg会话如下所示

!clrstack -a
ConsoleApp.Program.Main(System.String[]) [c:\visual studio 2012\Projects\Algorithms\ConsoleApp\Program.cs @ 36]
    PARAMETERS:
        args (0x00bff274) = 0x02ba2fbc
    LOCALS:
        0x00bff270 = 0x02ba2fd8

0x02ba2fd8是MyClass实例的地址,接下来我要尝试转储MyClass实例。

!do 0x02ba2fd8

Name:        ConsoleApp.MyClass
MethodTable: 00f84d74
EEClass:     00f81840
Size:        12(0xc) bytes
File:        C:\visual studio 2012\Projects\Algorithms\ConsoleApp\bin\Debug\ConsoleApp.exe
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
601a4544  4000001        4         System.Int32  1 instance       10 Z

下一步是转储方法表(其地址为00f84d74)。

!dumpmt -md 00f84d74

EEClass:         00f81840
Module:          00f83fbc
Name:            ConsoleApp.MyClass
mdToken:         02000002
File:            C:\visual studio 2012\Projects\Algorithms\ConsoleApp\bin\Debug\ConsoleApp.exe
BaseSize:        0xc
ComponentSize:   0x0
Slots in VTable: 6
Number of IFaces in IFaceMap: 0
--------------------------------------
MethodDesc Table
   Entry MethodDe    JIT Name
6005a2c8 5fcf8354 PreJIT System.Object.ToString()
60065600 5fcf835c PreJIT System.Object.Equals(System.Object)
600319b0 5fcf837c PreJIT System.Object.GetHashCode()
600316e8 5fcf8390 PreJIT System.Object.Finalize()
012604c0 00f84d6c    JIT ConsoleApp.MyClass..ctor()
012604f8 00f84d60    JIT ConsoleApp.MyClass.M()

从!dumpmt命令的输出可以看出,方法表包含M()方法的条目。但是当我尝试在地址00f84d74处转储内存时:

The output from !dumpmt命令显示方法表包含M()方法的条目。但是当我尝试在地址00f84d74转储内存时,出现了问题:

dd  00f84d74

00f84d74  00000200 0000000c 00024188 00000004
00f84d84  601a299c 00f83fbc 00f84db0 00f81840
00f84d94  012604c0 00000000 00f84da0 6005a2c8
00f84da4  60065600 600319b0 600316e8 00000080
00f84db4  00000000 03ba3500 00000000 03ba3504
00f84dc4  00000000 00000000 00000000 00000000
00f84dd4  00000000 00000000 00000000 00000000
00f84de4  00000000 00000000 00000000 00000000

我找不到M()方法(012604f8)的地址引用。

所以问题在于方法表是否包含对非虚拟方法的引用?它们存储在哪里?


1
012604f8是方法元数据描述的地址。方法表不仅包含方法地址,还包括从Object继承的4个虚方法,其起始地址为00f84da0(6005a2c8等),该类的两个方法尚未被JIT编译。 - Hans Passant
谢谢,汉斯。方法M()已经进行了JIT编译。但是在方法表中没有M()的条目。 - dmitryo
1个回答

7

在此输入图片描述

感谢我的一位同事为我的问题提供了一些启示。事实证明,方法指针相对于方法表指针位于负偏移量处。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接