]
Gail Badner updated HHH-2631:
-----------------------------
Attachment: HHH-2631.patch
I am attaching a patch that removes references to ResultSet objects from
CollectionLoadContext and LoadContexts when they are no longer needed, and removes
CollectionKey objects from CollectionLoadContext.localLoadingCollectionKeys as they are
processed by CollectionLoadContext.endLoadingCollections(CollectionPersister persister).
In CollectionLoadContext.endLoadingCollections(CollectionPersister persister), I noticed
that it would be more efficient to iterate over localLoadingCollectionKeys rather than
loadContexts.getLoadingCollectionEntryMap().entrySet(), since it can be a much smaller set
and each element will refer to a collection being loaded from the relevant ResultSet. This
patch makes this change in iterator.
I used loadContexts.locateLoadingCollectionEntry( collectionKey ) to get the
LoadingCollectionEntry. When a match in Persister and ResultSet is found, iter.remove()
removes the CollectionKey from localLoadingCollectionKeys and a new method,
loadContexts.unregisterLoadingCollectionEntry( collectionKey ), is called to remove the
entry from the cross-reference map in loadContexts.
When all elements of localLoadingCollectionKeys have been removed, then all collections
that are loaded from the ResultSet have been processed and the CollectionLoadContext
object (and its ResultSet reference) is no longer needed. A new method,
loadContexts.removeCollectionLoadContext(this), is called to remove the two references to
the ResultSet object in loadContexts.collectionLoadContexts (the key and in the
CollectionLoadContext value).
I'm not completely sure that it is appropriate to remove the CollectionLoadContext
from loadContexs.collectionLoadContexts after the last CollectionKey in
localLoadingCollectionKeys is processed. Would it be better to call LoadContexts.cleanup()
when the session is being closed?
I've verified that no unit tests are broken by this patch.
Leaking PreparedStatement and ResultSet via CollectionLoadContext
instances maintained in Map collectionLoadContexts in LoadContexts
------------------------------------------------------------------------------------------------------------------------------------
Key: HHH-2631
URL:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-2631
Project: Hibernate3
Issue Type: Bug
Components: core
Affects Versions: 3.2.4
Environment: hibernate 3.2.3 with patch from HHH-2553
Reporter: Douglas A. Herrick
Assignee: Steve Ebersole
Fix For: 3.2.5, 3.3
Attachments: HHH-2631.patch
While diagnosing an apparent resource issue, while running our application for a couple
of hours I noticed over time that the number of PreparedStatement and ResultSet instances
continued to grow, eventually consuming a fair amount of memory. After digging around a
bit, I saw that the entries LoadContext.java inserts into the map named
collectionLoadContexts are not removed from the map [method cleanup(ResultSet resultSet)
might have removed them, but I never witnessed its invocation, nor did I find any
references to it).
I pasted below a stack trace that shows the insertion of elements into
collectionLoadContexts:
Thread [http-9943-Processor2] (Suspended (breakpoint at line 53 in
CollectionLoadContext))
CollectionLoadContext.<init>(LoadContexts, ResultSet) line: 53
LoadContexts.getCollectionLoadContext(ResultSet) line: 85
BasicCollectionLoader(Loader).handleEmptyCollections(Serializable[], Object,
SessionImplementor) line: 1060
BasicCollectionLoader(Loader).doQuery(SessionImplementor, QueryParameters, boolean)
line: 690
BasicCollectionLoader(Loader).doQueryAndInitializeNonLazyCollections(SessionImplementor,
QueryParameters, boolean) line: 236
BasicCollectionLoader(Loader).loadCollection(SessionImplementor, Serializable, Type)
line: 1994
BasicCollectionLoader(CollectionLoader).initialize(Serializable, SessionImplementor)
line: 36
BasicCollectionPersister(AbstractCollectionPersister).initialize(Serializable,
SessionImplementor) line: 565
DefaultInitializeCollectionEventListener.onInitializeCollection(InitializeCollectionEvent)
line: 60
SessionImpl.initializeCollection(PersistentCollection, boolean) line: 1716
PersistentSet(AbstractPersistentCollection).forceInitialization() line: 454
StatefulPersistenceContext.initializeNonLazyCollections() line: 785
QueryLoader(Loader).doQueryAndInitializeNonLazyCollections(SessionImplementor,
QueryParameters, boolean) line: 241
QueryLoader(Loader).doList(SessionImplementor, QueryParameters) line: 2220
QueryLoader(Loader).listIgnoreQueryCache(SessionImplementor, QueryParameters) line:
2104
QueryLoader(Loader).list(SessionImplementor, QueryParameters, Set, Type[]) line: 2099
QueryLoader.list(SessionImplementor, QueryParameters) line: 378
QueryTranslatorImpl.list(SessionImplementor, QueryParameters) line: 338
HQLQueryPlan.performList(QueryParameters, SessionImplementor) line: 172
SessionImpl.list(String, QueryParameters) line: 1121
QueryImpl.list() line: 79
HibQuery.list() line: 60
HibRepository(AbstractRepository).query(IQuery, Class) line: 300
...
While subsequent to this logic, hibernate does close the PreparedStatement and ResultSet
instances, since it never removes them from collectionLoadContexts map, those instances
are never GCed. After running our application for a couple of days the amount of storage
attributed to this potential leak is significant.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: