Description
The AssemblyLoadContext of any type that has undergone data contract serialization cannot be unloaded / collected. The specific offender is DataContractCriticalHelper, which has a few static caches and also retains a reference to the most-recently-serialized type.
Reproduction Steps
- Create a collectible AssemblyLoadContext
- Load a DataContractSerializable type into the collectible ALC
- Instantiate the collectible type
- Serialise the instance using something like:
varser=newDataContractSerializer(type);using(varms=newSystem.IO.MemoryStream()){ser.WriteObject(ms,document);varbytes=ms.ToArray();returnSystem.Text.Encoding.UTF8.GetString(bytes,0,bytes.Length);}- Invoke Unload() on the collectible ALC
- Trigger a garbage collection (collect / finalise / collect)
- Review loaded assemblies using a debugger or something like AppDomain.CurrentDomain.GetAssemblies()
- Observe that the collectible ALC / assembly has not unloaded.
- Repeat steps but skip step 4 and observer that the ALC / assembly has unloaded properly
Expected behavior
Unloading and collecting results in proper collection of collectible types / assemblies / contexts.
Actual behavior
Collectible types / assemblies / contexts that have been data contract serialised cannot be collected.
Regression?
No response
Known Workarounds
The following code allows proper collection to occur:
privatestaticvoidClearDataContractCaches(){vart=AppDomain.CurrentDomain.GetAssemblies().SelectMany(x =>x.GetTypes()).Single(x =>x.Name=="DataContractCriticalHelper");varstaticCache=t.GetFields(BindingFlags.NonPublic|BindingFlags.Static).Select(x =>x.GetValue(t)).ToArray();foreach(vardictionaryinstaticCache.OfType<IDictionary>())dictionary.Clear();foreach(vararrayinstaticCache.OfType<Array>()){for(vari=0;i<array.Length;I++){array.SetValue(null,i);}}varhandleBreaker=newDataContractSerializer(typeof(object));varo=newobject();using(varms=newMemoryStream()){handleBreaker.WriteObject(ms,o);}}Configuration
.NET 6
macOS Ventura 13.0
ARM64
Other information
No response
Description
The AssemblyLoadContext of any type that has undergone data contract serialization cannot be unloaded / collected. The specific offender is DataContractCriticalHelper, which has a few static caches and also retains a reference to the most-recently-serialized type.
Reproduction Steps
Expected behavior
Unloading and collecting results in proper collection of collectible types / assemblies / contexts.
Actual behavior
Collectible types / assemblies / contexts that have been data contract serialised cannot be collected.
Regression?
No response
Known Workarounds
The following code allows proper collection to occur:
Configuration
.NET 6
macOS Ventura 13.0
ARM64
Other information
No response