ASP.Net Core应用部件程序集无法卸载问题排查求助
排查可回收加载上下文无法卸载的残留引用
针对你遇到的应用部件卸载后Collectible AssemblyLoadContext无法正常卸载的问题,以下是几个重点排查方向:
1. 检查ActionDescriptor及路由相关的残留引用
虽然ActionDescriptionCollection已更新,但路由系统或Action处理链中可能存在旧对象的缓存:
- 查看
EndpointDataSource(尤其是MvcEndpointDataSource)的实例,确认来自目标程序集的Endpoint是否已被完全移除。部分路由缓存可能不会自动刷新,需手动触发路由重建。 - 检查自定义筛选器、模型绑定器或视图组件是否持有旧
ActionDescriptor的引用,这类组件常被缓存到Mvc系统的内部集合中。
2. DI容器中的服务残留
如果目标程序集的类型被注册到DI容器:
- 排查Singleton服务:Singleton实例会一直存活到应用终止,若持有程序集类型引用,会直接阻止加载上下文卸载。需确认是否有未清理的Singleton注册或实例。
- 检查Scoped服务:若存在未释放的Scoped服务实例(比如当前请求未结束,或某个Scoped服务被意外提升为Singleton),也会残留引用。
3. 应用部件Feature的缓存
ApplicationPartManager的FeatureProviders生成的Feature集合可能被其他服务缓存:
- 获取
ControllerFeature、ViewComponentFeature等实例,确认其中是否还包含目标程序集的类型。部分内部服务(如IMvcFeatureProviderCache)可能缓存旧的Feature数据。 - 尝试手动调用
ApplicationPartManager.PopulateFeature<TFeature>刷新Feature,再检查加载上下文状态。
4. 深入Windbg分析
用Windbg做更精准的根引用查找:
- 找到目标程序集的对象地址:
!dumpheap -type Assembly - 针对该地址查找所有根引用:
注意排查弱引用队列、终结器队列中的引用,以及加载上下文自身的关联对象。!gcroot <assembly-address> - 查看加载上下文状态:
找到对应的Collectible AssemblyLoadContext,检查!dumpdomainIsUnloaded属性,以及关联模块的引用计数。
5. 静态引用与JIT代码
- 检查目标程序集是否有静态字段、静态构造函数持有外部引用,或被其他静态类引用。静态引用会绕过GC回收,阻止加载上下文卸载。
- 若程序集类型被JIT编译,可尝试使用
!dumpmodule <module-address>查看模块的引用计数,确认是否有本机代码层面的残留引用。
6. 自定义变更通知组件的问题
检查你的CustomActionDescriptorChangeProvider:
- 是否所有依赖该Provider的服务都正确响应了变更?比如某些自定义缓存服务可能未监听变更事件,导致旧数据残留。
- 确认
TokenSource.Cancel()后,所有关联的CancellationToken是否已正确传递到相关服务,触发缓存清理。
内容的提问来源于stack exchange,提问作者Georgi Yankov
相关产品推荐
相关产品推荐

