迁移JPA数据模型至Java17+SpringBoot3.1后遇OOM问题求助
SpringBoot 3.1.3 + JPA 启动内存溢出问题求助
我正在基于现有JPA数据模型搭建新应用,使用SpringBoot 3.1.3 + Java17。该数据模型此前在Java11+SpringBoot2.7.x环境下的多个应用中运行正常。
升级过程中:
- 用OpenRewrite完成了从
javax到jakarta的迁移,构建无报错 - 修复了一处Hibernate报错的无效
@Table(indexes={@Index(...)})注解(该注解在SpringBoot2.7环境下未被检测) - 将所有
@Type(type = "yes_no")替换为@Convert(converter = YesNoConverter.class),解决了Hibernate的相关报错
修复后构建正常,但启动时出现内存溢出(OUT OF MEMORY),即使分配数GB最大堆内存也无法解决。
启动初期日志
2023-09-21T16:46:56.550+02:00 INFO 81372 --- [ restartedMain] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default] 2023-09-21T16:46:56.573+02:00 INFO 81372 --- [ restartedMain] org.hibernate.Version : HHH000412: Hibernate ORM core version 6.2.7.Final 2023-09-21T16:46:56.574+02:00 INFO 81372 --- [ restartedMain] org.hibernate.cfg.Environment : HHH000406: Using bytecode reflection optimizer 2023-09-21T16:46:56.647+02:00 INFO 81372 --- [ restartedMain] o.h.b.i.BytecodeProviderInitiator : HHH000021: Bytecode provider name : bytebuddy 2023-09-21T16:46:56.709+02:00 INFO 81372 --- [ restartedMain] o.s.o.j.p.SpringPersistenceUnitInfo : No LoadTimeWeaver setup: ignoring JPA class transformer 2023-09-21T16:46:56.718+02:00 INFO 81372 --- [ restartedMain] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting... 2023-09-21T16:46:56.931+02:00 INFO 81372 --- [ restartedMain] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Added connection oracle.jdbc.driver.T4CConnection@51420c43 2023-09-21T16:46:56.933+02:00 INFO 81372 --- [ restartedMain] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed. 2023-09-21T16:46:57.517+02:00 INFO 81372 --- [ restartedMain] o.h.b.i.BytecodeProviderInitiator : HHH000021: Bytecode provider name : bytebuddy
内存溢出报错日志
2023-09-21T16:49:44.584+02:00 WARN 81372 --- [ restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Java heap space 2023-09-21T16:49:44.585+02:00 INFO 81372 --- [ restartedMain] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated... 2023-09-21T16:49:44.595+02:00 INFO 81372 --- [ restartedMain] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed. 2023-09-21T16:49:44.598+02:00 INFO 81372 --- [ restartedMain] o.apache.catalina.core.StandardService : Stopping service [Tomcat] 2023-09-21T16:49:44.609+02:00 INFO 81372 --- [ restartedMain] .s.b.a.l.ConditionEvaluationReportLogger : Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled. 2023-09-21T16:49:44.622+02:00 ERROR 81372 --- [ restartedMain] o.s.boot.SpringApplication : Application run failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Java heap space at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1770) ~[spring-beans-6.0.11.jar:6.0.11] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:598) ~[spring-beans-6.0.11.jar:6.0.11] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520) ~[spring-beans-6.0.11.jar:6.0.11] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[spring-beans-6.0.11.jar:6.0.11] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.0.11.jar:6.0.11] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[spring-beans-6.0.11.jar:6.0.11] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.0.11.jar:6.0.11] at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1155) ~[spring-context-6.0.11.jar:6.0.11] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932) ~[spring-context-6.0.11.jar:6.0.11] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:608) ~[spring-context-6.0.11.jar:6.0.11] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.1.3.jar:3.1.3] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734) ~[spring-boot-3.1.3.jar:3.1.3] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:436) ~[spring-boot-3.1.3.jar:3.1.3] at org.springframework.boot.SpringApplication.run(SpringApplication.java:312) ~[spring-boot-3.1.3.jar:3.1.3] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-3.1.3.jar:3.1.3] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-3.1.3.jar:3.1.3] at eu.ecg.eureka.rlp.fmp.migration.Application.main(Application.java:20) ~[classes/:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na] at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) ~[spring-boot-devtools-3.1.3.jar:3.1.3] Caused by: java.lang.OutOfMemoryError: Java heap space at java.base/java.util.Arrays.copyOf(Arrays.java:3537) ~[na:na] at java.base/java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:228) ~[na:na] at java.base/java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:582) ~[na:na] at java.base/java.lang.StringBuilder.append(StringBuilder.java:179) ~[na:na] at org.hibernate.sql.ast.spi.AbstractSqlAstTranslator.appendSql(AbstractSqlAstTranslator.java:517) ~[hibernate-core-6.2.7.Final.jar:6.2.7.Final] at org.hibernate.sql.ast.tree.expression.ColumnReference$$Lambda$1307/0x0000000801015930.accept(Unknown Source) ~[na:na] at org.hibernate.sql.ast.tree.expression.ColumnReference.appendReadExpression(ColumnReference.java:191) ~[hibernate-core-6.2.7.Final.jar:6.2.7.Final] at org.hibernate.sql.ast.tree.expression.ColumnReference.appendReadExpression(ColumnReference.java:196) ~[hibernate-core-6.2.7.Final.jar:6.2.7.Final] at org.hibernate.sql.ast.tree.expression.ColumnReference.appendReadExpression(ColumnReference.java:171) ~[hibernate-core-6.2.7.Final.jar:6.2.7.Final] at org.hibernate.sql.ast.spi.AbstractSqlAstTranslator.visitColumnReference(AbstractSqlAstTranslator.java:6086) ~[hibernate-core-6.2.7.Final.jar:6.2.7.Final] at org.hibernate.sql.ast.tree.expression.ColumnReference.accept(ColumnReference.java:222) ~[hibernate-core-6.2.7.Final.jar:6.2.7.Final] at org.hibernate.sql.ast.spi.AbstractSqlAstTranslator.renderExpressionAsClauseItem(AbstractSqlAstTranslator.java:5035) ~[hibernate-core-6.2.7.Final.jar:6.2.7.Final] at org.hibernate.sql.ast.spi.AbstractSqlAstTranslator.renderSelectExpression(AbstractSqlAstTranslator.java:5020) ~[hibernate-core-6.2.7.Final.jar:6.2.7.Final] at org.hibernate.sql.ast.spi.AbstractSqlAstTranslator.visitSqlSelectExpression(AbstractSqlAstTranslator.java:5015) ~[hibernate-core-6.2.7.Final.jar:6.2.7.Final] at org.hibernate.sql.ast.spi.AbstractSqlAstTranslator.visitSqlSelection(AbstractSqlAstTranslator.java:4997) ~[hibernate-core-6.2.7.Final.jar:6.2.7.Final] at org.hibernate.dialect.OracleSqlAstTranslator.visitSqlSelection(OracleSqlAstTranslator.java:98) ~[hibernate-core-6.2.7.Final.jar:6.2.7.Final] at org.hibernate.sql.ast.spi.AbstractSqlAstTranslator.visitSqlSelections(AbstractSqlAstTranslator.java:4662) ~[hibernate-core-6.2.7.Final.jar:6.2.7.Final] at org.hibernate.sql.ast.spi.AbstractSqlAstTranslator.visitSelectClause(AbstractSqlAstTranslator.java:4563) ~[hibernate-core-6.2.7.Final.jar:6.2.7.Final] at org.hibernate.sql.ast.spi.AbstractSqlAstTranslator.visitQuerySpec(AbstractSqlAstTranslator.java:3031) ~[hibernate-core-6.2.7.Final.jar:6.2.7.Final] at org.hibernate.dialect.OracleSqlAstTranslator.visitQuerySpec(OracleSqlAstTranslator.java:269) ~[hibernate-core-6.2.7.Final.jar:6.2.7.Final] at org.hibernate.sql.ast.tree.select.QuerySpec.accept(QuerySpec.java:119) ~[hibernate-core-6.2.7.Final.jar:6.2.7.Final] at org.hibernate.sql.ast.spi.AbstractSqlAstTranslator.visitSelectStatement(AbstractSqlAstTranslator.java:986) ~[hibernate-core-6.2.7.Final.jar:6.2.7.Final] at org.hibernate.sql.ast.spi.AbstractSqlAstTranslator.translateSelect(AbstractSqlAstTranslator.java:849) ~[hibernate-core-6.2.7.Final.jar:6.2.7.Final] at org.hibernate.sql.ast.spi.AbstractSqlAstTranslator.translate(AbstractSqlAstTranslator.java:799) ~[hibernate-core-6.2.7.Final.jar:6.2.7.Final] at org.hibernate.loader.ast.internal.SingleIdLoadPlan.<init>(SingleIdLoadPlan.java:67) ~[hibernate-core-6.2.7.Final.jar:6.2.7.Final] at org.hibernate.loader.ast.internal.SingleIdEntityLoaderStandardImpl.createLoadPlan(SingleIdEntityLoaderStandardImpl.java:197) ~[hibernate-core-6.2.7.Final.jar:6.2.7.Final] at org.hibernate.loader.ast.internal.SingleIdEntityLoaderStandardImpl.prepare(SingleIdEntityLoaderStandardImpl.java:55) ~[hibernate-core-6.2.7.Final.jar:6.2.7.Final] at org.hibernate.persister.entity.AbstractEntityPersister.prepareLoader(AbstractEntityPersister.java:3447) ~[hibernate-core-6.2.7.Final.jar:6.2.7.Final] at org.hibernate.persister.entity.AbstractEntityPersister.postInstantiate(AbstractEntityPersister.java:3441) ~[hibernate-core-6.2.7.Final.jar:6.2.7.Final] at org.hibernate.metamodel.model.domain.internal.MappingMetamodelImpl.finishInitialization(MappingMetamodelImpl.java:204) ~[hibernate-core-6.2.7.Final.jar:6.2.7.Final] at org.hibernate.internal.SessionFactoryImpl.initializeMappingModel(SessionFactoryImpl.java:320) ~[hibernate-core-6.2.7.Final.jar:6.2.7.Final] at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:270) ~[hibernate-core-6.2.7.Final.jar:6.2.7.Final]
补充:注解替换示例
// FIXME: @Type(type = "yes_no") @Convert(converter = YesNoConverter.class) private boolean editable = true;
排查建议
- 生成内存dump分析:启动时添加JVM参数
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/指定路径/dump.hprof,用MAT(Memory Analyzer Tool)或VisualVM打开dump文件,定位占用内存最多的对象,从报错栈看大概率是Hibernate生成SQL时的字符串无限膨胀。 - 检查实体关联配置:排查双向关联是否正确设置了
mappedBy,有没有出现循环关联导致Hibernate在生成查询时陷入无限递归;检查是否有实体的关联字段未正确标注,导致Hibernate错误地解析出大量冗余关联。 - 验证Hibernate 6映射兼容性:Hibernate 6对比5.x有不少映射逻辑变化,比如注解解析、类型处理,检查是否有自定义类型、遗留的旧注解(比如未替换完全的javax相关注解)、或者复杂的@Formula/@Subselect等注解未适配新版本。
- 逐步缩小实体范围:临时注释掉部分实体类,重新启动应用,找到导致内存溢出的具体实体,再针对性排查该实体的映射配置。
- 检查Oracle方言配置:显式指定Hibernate的Oracle方言版本,比如`spring.jpa.properties.hibernate.dialect=org.hibernate.dial
相关产品推荐
相关产品推荐

