You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
WIP API Proposal - AssemblyBuilder.DefineDynamicAssembly for AssemblyLoadContext #29842
AssemblyBuilder is implemented as a type of RuntimeAssembly, but there seems to be no mechanism to create it directly in a specific AssemblyLoadContext.
I assume we need at least one mechanism.
This issue is highly similar to that described in #29042
If we chose a similar solution, we would need 2 changes.
Make existing APIs sensitive to AssemblyLoadContext.CurrentContextualReflectionContext
Add new explicit APIs
We may be able to support 1 above in 3.0 as this may be a simple PR.
It would be nice to add the new APIs for 3.1, but this may not meet the shiproom approval process
Or maybe these should not be deriving from RuntimeAssembly but rather Assembly. It seems very odd to be building an assembly while it is already loaded.
👍 I agree we should try to modify the existing APIs in 3.0. The new API - we'll see, this is relatively small change, so maybe it would still be possible to fit it in.
Wouldn't it be possible to provide an AssemblyLoadContext.DefineDynamicAssembly function ? The Contextual-API would require extensive locking when using thread-bound AssemblyLoadContexts, which is very common when migrating from AppDomain to AssemblyLoadContext.
It's a very good proposal because we cannot define a dynamic assembly on a new AppDomain (this documentation is by consequent completely wrong).
Moreover, regarding to this issue dotnet/docs#10149, dynamic assemblies are never collected by the garbage collector so currently, it's not possible to create assemblies and unload them which is a huge problem...
In the meantime, if this feature is not included in 3.0, is there a workaround to create assemblies and collect them? (my goal is to create types during a request lifetime)
dynamic assemblies are never collected by the garbage collector
Dynamic assemblies created with AssemblyBuilderAccess.RunAndCollect are collected by the garbage collector. Try to pass AssemblyBuilderAccess.RunAndCollect to AssemblyBuilder.DefineDynamicAssembly.
My assemblies are created with RunAndCollect flag, however they are never collected...
This is a test class which shows this issue (last assertion fails, weak reference is still alive because assembly is not collected)
@vitek-karas Thanks for your reply, your code works even without NoInlining flag. I guess this is because object instance is declared in separated function but never used in the Main one.
Now, if I change the test to use the created object (this is the goal), test fails:
Here, set the instance to null is not enough, so am I obliged to always use a WeakReference?
setting a variable to null doesn't mean that there is no reference to the object anymore. JIT can create helper locals with longer lifetime. If you put the lines that create the instance into a separate non-inlineable function and call that from CheckIfAssemblyIsCollected, it should work too. That would ensure that the reference to your object cannot escape to some place that you don't expect.
#48072 implemented the change in existing APIs. I'm leaving this issue opened to track the work to add a new API which can explicitly state the load context to use.
Activity
sdmaclea commentedon Jun 10, 2019
Maybe these automatically should get their own private AssemblyLoadContext?
sdmaclea commentedon Jun 10, 2019
Or maybe these should not be deriving from
RuntimeAssemblybut ratherAssembly. It seems very odd to be building an assembly while it is already loaded.jkotas commentedon Jun 11, 2019
I am not sure how this would look like.
RuntimeAssemblyis internal impl detail of CoreLib.jkotas commentedon Jun 11, 2019
This sounds good to me.
AssemblyBuilder.DefineDynamicAssemblyis one of those APIs that uses the implicit load context of the immediate caller: https://github.com/dotnet/coreclr/blob/master/src/vm/assembly.cpp#L561vitek-karas commentedon Jun 11, 2019
👍 I agree we should try to modify the existing APIs in 3.0. The new API - we'll see, this is relatively small change, so maybe it would still be possible to fit it in.
dh1dm commentedon Jul 15, 2019
Wouldn't it be possible to provide an AssemblyLoadContext.DefineDynamicAssembly function ? The Contextual-API would require extensive locking when using thread-bound AssemblyLoadContexts, which is very common when migrating from AppDomain to AssemblyLoadContext.
sdmaclea commentedon Jul 15, 2019
@dh1dm Adding a new API is the preferred approach. The issue was discovered too late to be included in 3.0.
Not sure why any locking would be required as
AssemblyLoadContext.CurrentContextualReflectionContextis stored in anAsyncLocal<T>.dh1dm commentedon Jul 15, 2019
Ok, that's true, thanks for info.
Adriien-M commentedon Aug 20, 2019
What is the status of this issue?
It's a very good proposal because we cannot define a dynamic assembly on a new
AppDomain(this documentation is by consequent completely wrong).Moreover, regarding to this issue dotnet/docs#10149, dynamic assemblies are never collected by the garbage collector so currently, it's not possible to create assemblies and unload them which is a huge problem...
In the meantime, if this feature is not included in 3.0, is there a workaround to create assemblies and collect them? (my goal is to create types during a request lifetime)
vitek-karas commentedon Aug 20, 2019
/cc @janvorli who might know some tricks how to unload dynamic assemblies
jkotas commentedon Aug 20, 2019
Dynamic assemblies created with
AssemblyBuilderAccess.RunAndCollectare collected by the garbage collector. Try to passAssemblyBuilderAccess.RunAndCollecttoAssemblyBuilder.DefineDynamicAssembly.Adriien-M commentedon Aug 20, 2019
My assemblies are created with
RunAndCollectflag, however they are never collected...This is a test class which shows this issue (last assertion fails, weak reference is still alive because assembly is not collected)
Am I doing something wrong or is it a bug?
vitek-karas commentedon Aug 20, 2019
I think this is probably caused by inlining. This works (prints out
Trueand thenFalse):Adriien-M commentedon Aug 20, 2019
@vitek-karas Thanks for your reply, your code works even without
NoInliningflag. I guess this is because object instance is declared in separated function but never used in the Main one.Now, if I change the test to use the created object (this is the goal), test fails:
Here, set the instance to null is not enough, so am I obliged to always use a
WeakReference? Because in this case it works...janvorli commentedon Aug 20, 2019
setting a variable to null doesn't mean that there is no reference to the object anymore. JIT can create helper locals with longer lifetime. If you put the lines that create the instance into a separate non-inlineable function and call that from CheckIfAssemblyIsCollected, it should work too. That would ensure that the reference to your object cannot escape to some place that you don't expect.
9 remaining items
Ap0k commentedon Feb 9, 2021
Please see this PR #48072
vitek-karas commentedon Feb 10, 2021
I filed dotnet/dotnet-api-docs#5321 for some of the documentation issues around this (mentioned by several comments above).
vitek-karas commentedon Feb 16, 2021
#48072 implemented the change in existing APIs. I'm leaving this issue opened to track the work to add a new API which can explicitly state the load context to use.
Ap0k commentedon Feb 16, 2021
@vitek-karas DefineDynamicAssembly API Extension PR #48353