8

我在 asp.net Web 表单应用程序中使用 2.2.0.0 版的 Ninject,经过几百个请求后,它有时会在 Binding 类的 GetProvider 方法中引发 NullReferenceException。

示例堆栈跟踪: http: //pastebin.com/BbhsPQMT

仅当我对应用程序进行压力测试并且异常的来源通常不同(解析不同的接口)时才会发生异常。

为了试图理解为什么会出现这个问题,我查看了 Ninject 源代码并插入了一些代码行以进行调试。我后来确认为 null 的对象是 Binding 类中的 ProviderCallback 属性。

我还在 ProviderCallback 属性的 set 运算符中添加了一些代码,以便了解它是否被设置为 null。在运行了一些测试并查看了一些内存转储之后,似乎 ProviderCallback 属性没有设置为空值,因此我认为该实例正在由 GC 收集。

我仍然不明白为什么会这样......

任何帮助是极大的赞赏。

编辑:我们升级到最新版本的 Ninject 只是为了检查异常是否仍然发生,但在对应用程序进行压力测试后我们得到了相同的异常:http: //pastebin.com/YaiaZndz

4

1 回答 1

2

我无法告诉您此问题的原因,因为我无法重现这种行为。但是,您可以采取一些步骤来确定问题。

正如您所说,问题是由 a ProviderCallbackthat is引起的null。这不能由 GC 引起,因为 GC 永远不会分配null给属性。相反,您将得到一个已经处理的异常或其他奇怪的行为。但是还有其他一些原因会发生这种情况:

  1. Null是在某个时间分配的,但是由于您已经对此进行了验证,因此这不是原因。
  2. 它根本没有被分配。
  3. BindingConfiguration稍后会创建一个新的。

BindingConfiguration通过在构造函数中添加断点可以轻松验证第三点。在成功配置内核并开始解析对象后,不应再调用它。

对于第二个问题,在内核配置后执行以下命令:

var kernel = your fully configured kernel;
var bindingsField = typeof(KernelBase).GetField("bindings", BindingFlags.NonPublic | BindingFlags.Instance);
var bindings = bindingsField.GetValue(kernel) as IEnumerable<KeyValuePair<Type, ICollection<IBinding>>>;

foreach (var bindingsEntry in bindings
    .Where(bindingsEntry => bindingsEntry.Value
        .Any(binding => binding.BindingConfiguration.ProviderCallback == null)))
{
    throw new Exception(string.Format("No Provider callback defined for {0}.", bindingsEntry.Key));
}
于 2012-11-20T18:07:01.830 回答