Oracle TemporaryLobs导致Spring Boot应用内存泄漏求助
针对Spring Boot 2.7.x + Oracle 21c场景下Blob引发的OOM问题(根源为Oracle驱动temporaryLobs列表中Blob未释放,Spring JDBC 5.3.25无法直接操作该列表),可通过以下方式解决:
1. 对齐Oracle JDBC驱动与数据库版本
当前使用的ojdbc8 19.3.0.0与Oracle 21c版本不匹配,存在兼容性隐患。将驱动版本升级至与数据库一致的21.5.0.0,同时保持orai18n版本同步:
<dependency> <groupId>com.oracle.ojdbc</groupId> <artifactId>ojdbc8</artifactId> <version>21.5.0.0</version> </dependency> <dependency> <groupId>com.oracle.database.nls</groupId> <artifactId>orai18n</artifactId> <version>21.5.0.0</version> </dependency>
新版本驱动优化了临时LOB的生命周期管理,大概率能自动修复未释放问题。
2. 手动显式释放Blob资源
在代码中使用Blob后,务必在finally块中调用free()方法强制释放,避免资源滞留:
jdbcTemplate.execute("SELECT blob_col FROM target_table WHERE id = ?", (PreparedStatement ps) -> { ps.setLong(1, targetId); try (ResultSet rs = ps.executeQuery()) { if (rs.next()) { Blob blob = rs.getBlob("blob_col"); try { // 业务处理:读取Blob流、转换数据等 InputStream blobStream = blob.getBinaryStream(); // ... 具体业务逻辑 } finally { // 显式释放Blob资源 blob.free(); } } } return null; });
通过try-with-resources和finally双重保障,确保Blob资源被及时回收。
3. 配置驱动自动清理临时LOB参数
在数据库连接URL中添加oracle.jdbc.freeTemporaryLobsOnCommit=true,让驱动在事务提交时自动清理temporaryLobs列表:
spring.datasource.url=jdbc:oracle:thin:@//your-host:your-port/your-service?oracle.jdbc.freeTemporaryLobsOnCommit=true
该参数会触发驱动在事务完成后自动释放临时LOB,无需手动干预驱动内部列表。
4. 排查资源泄漏点
检查所有ResultSet、PreparedStatement的使用场景,确保通过try-with-resources语法自动关闭资源。Spring JDBC模板方法通常会自动处理,但自定义SQL回调时需手动保证资源闭环,避免因Statement/ResultSet未关闭导致Blob无法被回收。
5. 升级Spring JDBC版本(可选)
若上述方法无效,可升级Spring JDBC至5.3.x系列的最新补丁版本(如5.3.30),该版本对Oracle LOB的处理逻辑有优化。注意Spring Boot 2.7.x与Spring JDBC 5.3.x系列完全兼容,无需调整Boot主版本。
内容的提问来源于stack exchange,提问作者Matteo Rossi

