I am working on a Spring Boot 3.3.8 application with Hibernate 6.5.3 and a PostgreSQL 42.7.5. I have an entity that contains a column for storing binary data (bytea
in PostgreSQL), and I am persisting large files (e.g., 10MB PDF files) as byte arrays (byte[]).
The problem I am facing is that off-heap memory keeps growing and is never released, while heap memory behaves normally (it grows but is eventually cleaned by the garbage collector). If I continue uploading and persisting more PDF files, the system eventually runs out of memory, even though the JVM heap size remains stable.
The issue occurs when persisting byte arrays to the bytea column in PostgreSQL.
My questions:
- What could be causing the off-heap memory leak in this scenario?
- How can I ensure that large binary data stored in PostgreSQL is handled efficiently without exhausting off-heap memory?
- Are there specific Hibernate or PostgreSQL JDBC configurations/properties that will help to persist large byte arrays properly without leaking to off-heap memory and releasing it?
Below is how the column is mapped in entity:
@Basic(fetch = FetchType.LAZY)
@Column(name = "DOC_CONTENT", nullable = false)
private byte[] docContent;
Entity is persisted with EntityManager:
em.persist(entity);
Hibernate properties:
properties.put(ValidationSettings.JAKARTA_VALIDATION_MODE, "none");
properties.put(ValidationSettings.CHECK_NULLABILITY, Boolean.TRUE.toString());
properties.put(StatisticsSettings.GENERATE_STATISTICS, Boolean.FALSE.toString());
properties.put(JdbcSettings.STATEMENT_FETCH_SIZE, 10000);
properties.put(JdbcSettings.DIALECT, PostgreSQLDialect.class.getName());
properties.put(MappingSettings.DEFAULT_SCHEMA, "test_schema");
properties.put(MappingSettings.WRAPPER_ARRAY_HANDLING, WrapperArrayHandling.LEGACY);
Datasource used:
HikariDataSource dataSource = DataSourceBuilder.create().type(HikariDataSource.class).build();
Spring JPA properties:
spring.jpa.show-sql = false
spring.jpa.generate-ddl = false
spring.jpa.hibernate.ddl-auto = none
spring.jpa.open-in-view = false
spring.jpa.properties.hibernate.cache.use_second_level_cache = false
spring.jpa.properties.hibernate.cache.use_query_cache = false
spring.jpa.properties.hibernate.jdbc.batch_size = 30