在clr callstack中查看接口是否正常?

时间:2016-01-27 13:22:45

标签: c# .net interface clr callstack

我有一个asp.net应用程序,它崩溃了。在包含此callstack的Windows事件日志中有一个条目:

 Exception type: EntryPointNotFoundException 
    Exception message: Entry point was not found.
   at ***.Interfaces.Portal.Repository.ILookup.get_LookupDataCollection()
   at ***.Portal.Repository.Lookup.GetLookUpValue(ILookup lookup, Int32 index)
   at ***.Portal.Repository.Lookup.GetLookUpValue(ILookup lookup)
   at ***.HttpModules.RuntimeHttpModule.SetPageUrlInfoInContext(PageUrlInfo pinfo)
   at ***PortalRuntime.HttpModules.RuntimeHttpModule.BeginRequest(Object sender, EventArgs e)
   at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

这仅在客户机器上发生,我无法在本地重现。正如您在顶部看到的那样,有一个接口(ILookup,它实际上是一个接口,而不是一个类。)

我构建了一个类似的示例(通过接口调用的方法)。 Visual Studio 2015非常智能,可以显示:

ConsoleApplication2.exe!ConsoleApplication2.Lookup.GetLookupId(ConsoleApplication2.ILookup lookup) Line 37  C#

但是你仍然可以看到实现该方法的类。当应用程序位于通过接口调用的方法中的断点时,我还使用windbg附加到我的示例并打印堆栈:接口不在堆栈中。

这是我的问题:

  • 在clr callstack中查看接口是否正常(特别是没有实现它的类)?我想我以前从未见过这样的一个callstack ......其他人? (我的意思是这一般,无论我的问题的第二部分如何)

  • Here是一个非常相似的问题:@Hans Passant在他的第一条评论中说“未能解决接口方法的实现方法”,OP说“你已经回答了我的问题”第一条评论“。这真的是根本原因吗?有谁知道修复此问题?或者它只是一个特殊的CLR版本?

1 个答案:

答案 0 :(得分:7)

我可以解释为什么你会看到这一点,解决你的问题根本没有帮助。我对CLR将接口方法与其实现方式联系起来的方式了解得不够,它已经疯狂地进行了微观优化。

问题是抖动必须为包含接口方法调用的方法生成代码。但它还不知道对象引用的身份。在代码实际执行之前,这不知道100%准确。所以它的作用是为目标方法分配一个 stub ,一个占位符。并为该存根生成CALL指令。该存根方法的实际名称不相关,当真正的目标方法被解析时,它将再次消失。

存根本身会生成对CLR的调用以解析目标方法,现在知道对象引用的真实身份,从而知道需要执行哪种特定的实现方法。并修补机器代码,以便更换CALL地址。因此,方法执行的 next 时间您不需要支付方法绑定的价格,并且调用以最大可能的翘曲速度运行。

如上所述,存根的名称无关紧要,因为它是临时的。给它提供接口方法的名称非常有助于诊断MissingMethodException。好主意。

真正的问题是加载的程序集不是您构建代码的程序集。可能是您忘记重新部署的旧版本。或者您只是在更改界面时忘记重建它,因为它不是解决方案的一部分。因此它没有接口方法的实现,当存根执行时,CLR发现这很晚。所以你在调用堆栈上看到了stub方法名称。