Potential memory leak in QueryInterpretationCache


recently our Hibernate version was updated to 6.2.7.Final. Parameters like hibernate.query.plan_cache_enabled, hibernate.query.plan_cache_max_size, hibernate.query.plan_parameter_metadata_max_size were not specified, so I assume default ones were in effect.
We observed higher memory usage leading to OOMs in production environment. Heap dump analysis indicated a lot of objects associated with QueryInterpretationCache weren’t garbage collected (screenshot #1).

E. g. you can see almost 400k LIRSHashEntry objects consuming estimated 2G of heap. There’s also similar number of AliasToBeanResultTransformer and SelectInterpretationsKey.

Further analysis showed that number of top-level (contained in table fields of Segment class) LIRSHashEntry was indeed below default bound (2048). However many of them consisted a head of linked list which contained thousands of entries via next field (screenshot #2).

All of linked entries had the same hash and contained exactly the same query. Their keys were SelectInterpretationsKey instances. Their state field was set to HIR_NONRESIDENT, which I believe is an indication that entry was evicted from BoundedConcurrentHashMap. Most of 400k entries have similar state (screenshot #3).

I couldn’t reproduce this behaviour in local environment, so maybe it’s linked with higher volume and variety of queries in production app.

I’d be grateful for any suggestion on what’s happening here and how we can make the cache respect the entries limit.

I think you can track [HHH-13345] - Hibernate JIRA for updates on this matter.