I’m using springboot 3.0.5 and Hibernate 6.1.7
My project running on centos 7 with open-jdk 21.
After some hours the java thread cpu increase more than 100%.
I dumped the jvm heap and use MAT analyze it:
One instance of “org.hibernate.internal.util.collections.BoundedConcurrentHashMap$LIRSHashEntry” loaded by “org.springframework.boot.loader.LaunchedURLClassLoader @ 0x80000028” occupies 271,316,744 (74.66%) bytes.
Keywords
org.hibernate.internal.util.collections.BoundedConcurrentHashMap$LIRSHashEntry
org.springframework.boot.loader.LaunchedURLClassLoader @ 0x80000028
The properties setted:
spring.jpa.properties.hibernate.query.in_clause_parameter_padding=true
spring.jpa.properties.hibernate.query.plan_cache_max_size=32
spring.jpa.properties.hibernate.query.plan_parameter_metadata_max_size=32
I don’t know where the problem is.
Did anyone know about it?
Thanks a lot!
Use MAT analyze the dump file
2
Answers
After analyze, I set :
spring.jpa.properties.hibernate.query.plan_cache_enabled=false
It seems no memory leak.
This issue arises because JPQL statements need to be translated into actual SQL before they can be executed. JPA handles this translation process, which can be quite complex. To avoid the CPU overhead caused by frequently translating the same queries, JPA caches the translated JPQL statements. However, if the initial cache size is set too large, it can eventually lead to memory overflow.
To balance CPU usage and memory consumption, you can adjust the number of cached statements to 32. This adjustment helps maintain a good balance between performance and resource usage.
I’m using Spring Boot, and here’s how you configure it:
spring:
jpa:
properties:
hibernate:
query:
plan_cache_max_size: 32
plan_parameter_metadata_max_size: 32
Of course, you could also choose to disable caching entirely like the other person suggested. However, I recommend keeping a small cache so that frequently used queries don’t need to be translated into SQL every time they are executed.