-
Notifications
You must be signed in to change notification settings - Fork 192
Description
Issue
Executing an Oracle native SQL query via EclipseLink JPA that applies SUBSTR to a CLOB column and returns the result as a String causes steady heap growth over time. Heap dumps show retained objects rooted in oracle.jdbc.driver.T4CConnection, specifically the protected field:
HashMap<OracleLargeObject, String> temporaryLobs
With repeated query execution, the temporaryLobs map grows and entries are not released/cleared, leading to increased heap usage and eventual OOM under sustained load. Looks like temporary LOB tracking is not being cleaned up after result processing/statement completion in the EclipseLink native query execution path.
Evidence
- Heap dump / object histogram shows increasing retained size from oracle.jdbc.driver.T4CConnection.temporaryLobs and associated OracleLargeObject instances.
- Growth correlates directly with repeated execution of the native query shown below.
| Class Name | Shallow Heap | Retained Heap | Percentage |
|---|---|---|---|
| oracle.jdbc.driver.T4CConnection @ 0x6037fddf0 | 1,944 | 5,18,52,152 | 43.35% |
| |- temporaryLobs java.util.HashMap @ 0x6038dde80 | 48 | 5,14,32,832 | 43.00% |
| |- tempLobRefCount java.util.Hashtable @ 0x6038e4638 | 48 | 3,29,216 | 0.28% |
| |- oracle.net.ns.SessionAtts @ 0x6037f71e0 | 232 | 20,288 | 0.02% |
| |- connectionBufferCacheStore oracle.jdbc.driver.PhysicalConnection$BufferCacheStore @ 0x606c34098 | 24 | 19,984 | 0.02% |
| |- auth oracle.jdbc.driver.T4CTTIoauthenticate @ 0x6038df880 | 200 | 7,512 | 0.01% |
| |- methodTempLargeByteBuffer byte[4096] @ 0x6037fe768 | 4,112 | 4,112 | 0.00% |
| |- oracle.jdbc.driver.T4CPreparedStatement @ 0x605f15920 | 968 | 3,640 | 0.00% |
| |- sessionPropertiesCopy java.util.Properties @ 0x6038dc558 | 56 | 3,272 | 0.00% |
| |- statements oracle.jdbc.driver.T4CPreparedStatement @ 0x606c93218 | 968 | 3,024 | 0.00% |
| |- tempLobsToFree byte[2048] @ 0x6038e3888 | 2,064 | 2,064 | 0.00% |
| |- net oracle.net.ns.NSProtocolNIO @ 0x6037f72c8 | 48 | 1,872 | 0.00% |
| |- oracle.jdbc.driver.Accessor[1] @ 0x606c935e0 | 24 | 1,264 | 0.00% |
| |- statementCache oracle.jdbc.driver.LRUStatementCache @ 0x608bfb4f0 | 40 | 1,216 | 0.00% |
| |- oracle.net.nt.ConnOption @ 0x6037f73a0 | 152 | 848 | 0.00% |
| |- all8 oracle.jdbc.driver.T4C8Oall @ 0x6038e17d8 | 240 | 736 | 0.00% |
| |- okeyval oracle.jdbc.driver.T4CTTIokeyval @ 0x6038e2aa0 | 112 | 704 | 0.00% |
| |- java.util.Properties @ 0x6037f7710 | 56 | 696 | 0.00% |
| |- pipeline oracle.jdbc.driver.Pipeline @ 0x6038e4228 | 72 | 688 | 0.00% |
| |- driverResources oracle.jdbc.driver.resource.DriverResources @ 0x6037f7f08 | 16 | 640 | 0.00% |
| |- oaqenq oracle.jdbc.driver.T4CTTIoaqenq @ 0x6038e1ea8 | 168 | 504 | 0.00% |
| |- aqe oracle.jdbc.driver.T4Caqe @ 0x6038e1b38 | 160 | 456 | 0.00% |
| |- osaga oracle.jdbc.driver.T4CTTIosaga @ 0x6038e3698 | 152 | 448 | 0.00% |
| |- aqdq oracle.jdbc.driver.T4Caqdq @ 0x6038e1cf8 | 144 | 440 | 0.00% |
| |- oaqdeq oracle.jdbc.driver.T4CTTIoaqdeq @ 0x6038e20a0 | 144 | 440 | 0.00% |
| '- sun.nio.ch.SocketChannelImpl @ 0x6037f74f8 connected local=10.3.10.111:61503 remoteAddress=faeops-oci-cman.oraclecorp.com/138.3.98.170:1999 | 120 | 432 | 0.00% |
To Reproduce
Steps/resources to reproduce the behavior:
- EclipseLink version: 4.0.7
- Java/JDK: 21
- Database: Oracle Database
- JDBC driver: ojdbc11-23.7.0.25.01
- JPA usage: EntityManager.createNativeQuery(...) returning scalar String
- Connection pooling: UCP
Try to query a table with a CLOB column containing text data (at least >4000 chars) repeatedly from app
...
for (int i = 0; i < 2_000; i++) {
Query q = em.createNativeQuery(
"select substr(CLOB_COL, 1, 5000) as CLOB_COL " +
"from TABLE_NAME where ID = ?1"
);
q.setParameter(1, 1L);
List<String> rs = q.getResultList();
String s = rs.isEmpty() ? null : rs.get(0);
}
...
How to observe
- During the run take heap dumps periodically.
- In the heap dump, inspect retained references from oracle.jdbc.driver.T4CConnection and check growth in temporaryLobs.
Expected behavior
Temporary LOB bookkeeping should be released/cleared after result processing and statement completion. Heap usage should remain stable during repeated execution; oracle.jdbc.driver.T4CConnection.temporaryLobs should not grow unbounded.
Additional context
Running the same SQL repeatedly using direct JDBC (PreparedStatement + close ResultSet/Statement) does not show growth in temporaryLobs/