不可回收的 AssemblyLoadContext 中的可回收程序集

.NET 错误地允许垃圾回收程序集解析为不可回收的 AssemblyLoadContext。 在某些情况下,此操作会导致运行时崩溃或意外出现 NullReferenceException 异常。 此更改通过在 AssemblyLoadContext.Load(AssemblyName)AssemblyLoadContext.Resolving 事件返回可回收的 Assembly 并且 AssemblyLoadContext 不可回收时引发异常来阻止不正确的行为。

旧行为

AssemblyLoadContext.Load(AssemblyName) 替代中返回可回收的 Assembly 或不可回收的 AssemblyLoadContextAssemblyLoadContext.Resolving 事件不会引发任何异常。

新行为

AssemblyLoadContext.Load(AssemblyName) 替代中返回可回收的 Assembly 或不可回收的 AssemblyLoadContextAssemblyLoadContext.Resolving 事件会引发带有 NotSupportedException 作为内部异常的 System.IO.FileLoadException

引入的版本

.NET 7

中断性变更的类型

此项更改可能会影响二进制兼容性

更改原因

此更改修复了一个 bug。 可回收的 Assembly 将被执行垃圾回收操作,而引用它的 AssemblyLoadContext 在进程生存期的剩余时间内仍然存在。 如果在该上下文中运行的代码在收集后引用了 Assembly 中的任何内容,将会导致运行时崩溃或导致 NullReferenceExceptionAccessViolationException 或其他类型的错误行为。

不要返回 AssemblyLoadContext.Load(AssemblyName) 中的可回收程序集或不可回收的 AssemblyLoadContextAssemblyLoadContext.Resolving 事件。 一种可能的解决方法是将 AssemblyLoadContext 更改为可回收,这可以通过在其构造函数中为 isCollectible 参数传递 true 来实现,然后永久保留对 AssemblyLoadContext 的引用以确保它永远不会被回收。

受影响的 API

另请参阅