Skip to content

Memory Leak when fetching Temporary LOBS using Entity Manager Native Query #2642

@hanem42

Description

@hanem42

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/

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions