Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/core/compatibility/7.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ If you're migrating an app to .NET 7, the breaking changes listed here might aff
| - | :-: | :-: | - |
| [API obsoletions with non-default diagnostic IDs](core-libraries/7.0/obsolete-apis-with-custom-diagnostics.md) | ✔️ | ❌ | Preview 1 |
| [C++/CLI projects in Visual Studio](core-libraries/7.0/cpluspluscli-compiler-version.md)
| [Collectible Assembly in non-collectible AssemblyLoadContext](core-libraries/7.0/collectible-assemblies.md) | ❌ | ✔️ | Preview 5 |
| [FullPath and OldFullPath return fully qualified path](core-libraries/7.0/filesystemeventargs-fullpath.md) | ✔️ | ❌ | Preview 1 |
| [Generic type constraint on PatternContext\<T>](core-libraries/7.0/patterncontext-generic-constraint.md) | ❌ | ❌ | Preview 3 |
| [SerializationFormat.Binary is obsolete](core-libraries/7.0/serializationformat-binary.md) | ❌ | ❌ | Preview 2 |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
title: ".NET 7 breaking change: Collectible Assembly in non-collectible AssemblyLoadContext"
description: Learn about the .NET 7 breaking change in core .NET libraries where resolving a collectible Assembly in a non-collectible AssemblyLoadContext results in a FileLoadException.
ms.date: 05/10/2022
---
# Collectible Assembly in non-collectible AssemblyLoadContext

.NET incorrectly allowed garbage-collectible assemblies to resolve into a non-collectible <xref:System.Runtime.Loader.AssemblyLoadContext>. In some cases, this lead to runtime crashes or unexpected <xref:System.NullReferenceException> exceptions. This change prevents the incorrect behavior by throwing an exception when the <xref:System.Runtime.Loader.AssemblyLoadContext.Load(System.Reflection.AssemblyName)?displayProperty=nameWithType> or <xref:System.Runtime.Loader.AssemblyLoadContext.Resolving?displayProperty=nameWithType> event returns a collectible <xref:System.Type.Assembly> and the <xref:System.Runtime.Loader.AssemblyLoadContext> is non-collectible.

## Previous behavior

Returning a collectible <xref:System.Type.Assembly> in the <xref:System.Runtime.Loader.AssemblyLoadContext.Load(System.Reflection.AssemblyName)?displayProperty=nameWithType> override or the <xref:System.Runtime.Loader.AssemblyLoadContext.Resolving?displayProperty=nameWithType> event of a non-collectible <xref:System.Runtime.Loader.AssemblyLoadContext> doesn't cause any exceptions to be thrown.

## New behavior

Returning a collectible <xref:System.Type.Assembly> in the <xref:System.Runtime.Loader.AssemblyLoadContext.Load(System.Reflection.AssemblyName)?displayProperty=nameWithType> override or the <xref:System.Runtime.Loader.AssemblyLoadContext.Resolving?displayProperty=nameWithType> event of a non-collectible <xref:System.Runtime.Loader.AssemblyLoadContext> throws a <xref:System.IO.FileLoadException?displayProperty=fullName> with a <xref:System.NotSupportedException> as the inner exception.

## Version introduced

.NET 7 Preview 5

## Type of breaking change

This change can affect [binary compatibility](../../categories.md#binary-compatibility).

## Reason for change

This change fixes a bug. The collectible <xref:System.Type.Assembly> would be garbage-collected while the <xref:System.Runtime.Loader.AssemblyLoadContext> that has a reference to it is alive for the rest of the process lifetime. If the code running in that context references anything from that `Assembly` after it's collected, it would crash the runtime or result in a <xref:System.NullReferenceException>, <xref:System.AccessViolationException>, or other kinds of bad behavior.

## Recommended action

Don't return collectible assemblies in <xref:System.Runtime.Loader.AssemblyLoadContext.Load(System.Reflection.AssemblyName)?displayProperty=nameWithType> or the <xref:System.Runtime.Loader.AssemblyLoadContext.Resolving?displayProperty=nameWithType> event of a non-collectible <xref:System.Runtime.Loader.AssemblyLoadContext>. A possible workaround is to change the `AssemblyLoadContext` to be collectible by passing `true` for the `isCollectible` parameter in its constructor, and then keep a reference to that `AssemblyLoadContext` forever to make sure it's never collected.

## Affected APIs

- <xref:System.Runtime.Loader.AssemblyLoadContext.Load(System.Reflection.AssemblyName)?displayProperty=fullName>
- <xref:System.Runtime.Loader.AssemblyLoadContext.Resolving?displayProperty=fullName> event

## See also

- [Use collectible AssemblyLoadContext](../../../../standard/assembly/unloadability.md#use-collectible-assemblyloadcontext)
4 changes: 4 additions & 0 deletions docs/core/compatibility/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ items:
href: core-libraries/7.0/obsolete-apis-with-custom-diagnostics.md
- name: C++/CLI projects in Visual Studio
href: core-libraries/7.0/cpluspluscli-compiler-version.md
- name: Collectible Assembly in non-collectible AssemblyLoadContext
href: core-libraries/7.0/collectible-assemblies.md
- name: FullPath and OldFullPath return fully qualified path
href: core-libraries/7.0/filesystemeventargs-fullpath.md
- name: Generic type constraint on PatternContext<T>
Expand Down Expand Up @@ -729,6 +731,8 @@ items:
href: core-libraries/7.0/obsolete-apis-with-custom-diagnostics.md
- name: C++/CLI projects in Visual Studio
href: core-libraries/7.0/cpluspluscli-compiler-version.md
- name: Collectible Assembly in non-collectible AssemblyLoadContext
href: core-libraries/7.0/collectible-assemblies.md
- name: FullPath and OldFullPath return fully qualified path
href: core-libraries/7.0/filesystemeventargs-fullpath.md
- name: Generic type constraint on PatternContext<T>
Expand Down