在 clr 调用堆栈中看到接口是否正常?
Is it normal to see an interface in a clr callstack?
我有一个 asp.net 应用程序崩溃了。在包含此调用堆栈的 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
,它实际上是一个接口,而不是 class)。
我构建了一个类似的示例(通过接口调用的方法)。 Visual Studio 2015 年足够聪明,可以证明这一点:
ConsoleApplication2.exe!ConsoleApplication2.Lookup.GetLookupId(ConsoleApplication2.ILookup lookup) Line 37 C#
但是您仍然可以看到实现该方法的 class。我还使用 windbg 附加到我的示例,并在应用程序位于通过接口调用的方法中的断点时打印堆栈:接口不在堆栈上。
这是我的问题:
在 clr 调用堆栈中看到一个接口是否正常(尤其是没有实现它的 class)?我想我以前从未见过这样的调用堆栈……还有其他人吗? (我的意思是一般来说,不管我问题的第二部分)
Here 是一个非常相似的问题:@Hans Passant 在他的第一条评论中说“无法解析接口方法的实现方法”,OP 说“你已经回答了我的问题是你的第一条评论”。那么这真的是根本原因吗?有谁知道这个的修复方法?或者它只是一个特殊的 CLR 版本?
我可以稍微解释一下你为什么会看到这个,这对解决你的问题一点帮助都没有。我也不太了解 CLR 将接口方法绑定到它们的实现的方式,这太疯狂了 micro-optimized.
问题是抖动必须为包含接口方法调用的方法生成代码。但它还不能知道对象引用的身份。在代码实际执行之前,这并不知道 100% 准确。所以它所做的是分配一个 stub,一个目标方法的占位符。并为该存根生成一条 CALL 指令。该存根方法的实际名称无关紧要,当真正的目标方法被解析时,它将再次消失。
存根本身生成对 CLR 的调用以解析目标方法,现在知道对象引用的真实身份以及需要执行哪个具体实现方法。并修补机器代码,以便替换 CALL 地址。因此,在 下一次 方法执行时,您无需支付方法绑定的代价,并且调用以最大可能的扭曲速度运行。
如前所述,存根的名称并不重要,因为它是临时的。为其指定接口方法的名称非常有助于诊断 MissingMethodException。好主意。
真正的问题是加载的程序集不是您构建代码所用的程序集。可能是您忘记重新部署的旧版本。或者您只是在更改界面时忘记重建它,因为它不是解决方案的一部分。所以它没有接口方法的实现,当存根执行时,CLR 很晚才发现这一点。所以你在调用堆栈上看到存根方法名称。
我有一个 asp.net 应用程序崩溃了。在包含此调用堆栈的 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
,它实际上是一个接口,而不是 class)。
我构建了一个类似的示例(通过接口调用的方法)。 Visual Studio 2015 年足够聪明,可以证明这一点:
ConsoleApplication2.exe!ConsoleApplication2.Lookup.GetLookupId(ConsoleApplication2.ILookup lookup) Line 37 C#
但是您仍然可以看到实现该方法的 class。我还使用 windbg 附加到我的示例,并在应用程序位于通过接口调用的方法中的断点时打印堆栈:接口不在堆栈上。
这是我的问题:
在 clr 调用堆栈中看到一个接口是否正常(尤其是没有实现它的 class)?我想我以前从未见过这样的调用堆栈……还有其他人吗? (我的意思是一般来说,不管我问题的第二部分)
Here 是一个非常相似的问题:@Hans Passant 在他的第一条评论中说“无法解析接口方法的实现方法”,OP 说“你已经回答了我的问题是你的第一条评论”。那么这真的是根本原因吗?有谁知道这个的修复方法?或者它只是一个特殊的 CLR 版本?
我可以稍微解释一下你为什么会看到这个,这对解决你的问题一点帮助都没有。我也不太了解 CLR 将接口方法绑定到它们的实现的方式,这太疯狂了 micro-optimized.
问题是抖动必须为包含接口方法调用的方法生成代码。但它还不能知道对象引用的身份。在代码实际执行之前,这并不知道 100% 准确。所以它所做的是分配一个 stub,一个目标方法的占位符。并为该存根生成一条 CALL 指令。该存根方法的实际名称无关紧要,当真正的目标方法被解析时,它将再次消失。
存根本身生成对 CLR 的调用以解析目标方法,现在知道对象引用的真实身份以及需要执行哪个具体实现方法。并修补机器代码,以便替换 CALL 地址。因此,在 下一次 方法执行时,您无需支付方法绑定的代价,并且调用以最大可能的扭曲速度运行。
如前所述,存根的名称并不重要,因为它是临时的。为其指定接口方法的名称非常有助于诊断 MissingMethodException。好主意。
真正的问题是加载的程序集不是您构建代码所用的程序集。可能是您忘记重新部署的旧版本。或者您只是在更改界面时忘记重建它,因为它不是解决方案的一部分。所以它没有接口方法的实现,当存根执行时,CLR 很晚才发现这一点。所以你在调用堆栈上看到存根方法名称。