Potentially serious memory leak with regards to NHibernate.Action.EntityAction.BeforeTransactionCompletionProcessDelegate
Description
Environment
is duplicated by
Activity
Alex Zaytsev May 1, 2017 at 3:42 AM
Closing issues resolved in 4.1.0
Carlos Montagut February 23, 2016 at 3:44 PM
we just create the pull request.
Alex Zaytsev February 16, 2016 at 9:39 PM
the pull request will be highly appreciated
Carlos Montagut February 16, 2016 at 3:59 PM
We detected a similar issue in NHibernate.Action.CollectionAction and CollectionUpdateAction.
A list of AfterTransactionCompletionProcessDelegate is keept which have a reference to the related entities. These deletegates don't have any effect if the 2nd level cache is not activated, only consuming memory...
At the end of the transaction, doesn't matter if we called Session.Clean(), the entities are still referenced, consuming lot of memory.
We have documented this with a MemoryProfiler, and also we can build a kind of test, we spot this issue when Saving entities with OneToMany relations with cascade all. Also we can create a pull request with the suggested solution.
Oskar Berggren November 22, 2014 at 3:23 PM
Nominating for 4.1.
When I save some entities with Session.Save, I noticed all object states still live in the memory even if I flush and clear the session.
I used windbg and I saw ,the object states live in NHibernate.Action.EntityInsertAction.states field. However I couldn't understand why the object states still kept despite I cleared the session. Then from windbg I saw the following relation by running !gcroot
00000000029085f0(NHibernate.Impl.SessionImpl)->
00000000029086f8(NHibernate.Engine.ActionQueue)->
0000000002908b00(NHibernate.Engine.ActionQueue+BeforeTransactionCompletionProcessQueue)->
0000000002908b20(System.Collections.Generic.List`1[[NHibernate.Action.BeforeTransactionCompletionProcessDelegate, NHibernate]])->
000000000290c5d0(System.Object[])->
000000000290c590(NHibernate.Action.BeforeTransactionCompletionProcessDelegate)->
000000000290c060(NHibernate.Action.EntityInsertAction)
It is seen the EntityInsertAction is being hold by BeforeTransactionCompletionProcessDelegate.
I check the NHibernate.Action.EntityAction type and saw
Basically nhibernate keeps these delegates for interceptors and because of this, the EntityAction object lives in the memory ("this" pointer in above code).
However it is not so common that we have any listener for BeforeTransactionCompletion. So we are keeping the object state's for no reason. Look at same code for
As you see it checks if there is any requirements . If not then returns null. Same should be done for BeforeTransactionCompletionProcessDelegate
. I can't believe how this bug is lived so far. It is causing a lot of memory used for nothing.