I think there could be a possible memory leak.
Even the threads are not started witch I agree is the best, I see lot of weak references.
Looking at code:
Even cleaner will not be created, queueOfConnection gets a connection on every creation.
On a long living application that creates/closes many connections this queue grows to infinite.
I think.
/* 588 */ protected static final BlockingQueue<DelayedWeakReference<IfxSqliConnect>> queueOfConnections = new DelayQueue<>();
static synchronized <T extends IfxSqliConnect> void ensureConnectionMonitorThreadIsRunning(T connection) {
/* 597 */ long delay = IfxConnectionProperty.IFMXCONNECTION_CLEANER_DELAY_MAXIMUM.getLongValue((IfxSqliConnect)connection);
/* 598 */ queueOfConnections.offer(new DelayedWeakReference(connection, delay));
/* */
/* 600 */ if (cleaner == null) {
/* 601 */ int nThreads = IfxConnectionProperty.IFMXCONNECTION_CLEANER_THREADS.getIntValue((IfxSqliConnect)connection);
/* 602 */ if (nThreads > 0) {
/* 603 */ cleaner = Executors.newFixedThreadPool(nThreads, new IfxSqliConnectCleanerThreadFactory());
/* 604 */ for (int i = 0; i < nThreads; i++)
/* 605 */ cleaner.execute(new IfxSqliConnectCleaner());
/* */ }
/* */ }
/* */ }
Class Name | Shallow Heap | Retained Heap
--------------------------------------------------------------------------------------------------------------------------------------------------------
com.informix.jdbc.IfxSqli @ 0x6e0f7b7d0 | 312 | 2,101,048
'- prot com.informix.jdbc.IfxStatement @ 0x6e0f7b748 | 136 | 376
'- referent java.lang.ref.WeakReference @ 0x6e0f7b728 | 32 | 32
'- weakReferenceStmt com.informix.jdbc.IfxSqliConnect$StmtList @ 0x6e0f7ba68 | 24 | 56
'- [31] java.lang.Object[160] @ 0x69f9c9820 | 656 | 3,008
'- elementData java.util.Vector @ 0x68de64be0 | 32 | 3,040
'- stmtList com.informix.jdbc.IfxSqliConnect @ 0x68de601c8 | 376 | 14,208
'- referent com.informix.util.DelayedWeakReference @ 0x71c13de88 | 48 | 48
'- [56] java.lang.Object[343] @ 0x6cbe0def8 | 1,392 | 14,352
'- queue java.util.PriorityQueue @ 0x684c184a0 | 32 | 14,384
'- q java.util.concurrent.DelayQueue @ 0x6849d7c00 | 32 | 14,520
'- queueOfConnections class com.informix.jdbc.IfxSqliConnect @ 0x6849e5dc8 | 336 | 37,944
|- <class> com.informix.jdbc.IfxSqliConnect @ 0x6b53cc3b0 | 376 | 10,792
| |- <Java Local> java.lang.Thread @ 0x6849d7b00 IfxSqliConnectCleaner-Thread-1 Thread| 104 | 4,784
| |- jconn com.informix.jdbc.IfxStatement @ 0x71dfa3078 | 136 | 376
| |- conn com.informix.jdbc.IfxSqli @ 0x71dfa31b0 | 312 | 2,504
| |- conn com.informix.jdbc.IfxResultSet @ 0x71dfa5300 | 104 | 104
| |- conn com.informix.jdbc.IfxRowColumn @ 0x71dfaa008 | 48 | 48
| '- Total: 5 entries | |
|- <class> com.informix.jdbc.IfxSqliConnect @ 0x714f85588 | 376 | 8,832
|- <class> com.informix.jdbc.IfxSqliConnect @ 0x6950c8ec0 | 376 | 16,040
|- <class> com.informix.jdbc.IfxSqliConnect @ 0x6a09d5bb8 | 376 | 13,168
|- <class> com.informix.jdbc.IfxSqliConnect @ 0x6c3283988 | 376 | 15,832
|- <class> com.informix.jdbc.IfxSqliConnect @ 0x6eb3e70f8 | 376 | 7,392
|- <class> com.informix.jdbc.IfxSqliConnect @ 0x709f0db10 | 376 | 10,688
|- <class> com.informix.jdbc.IfxSqliConnect @ 0x70c3c3250 | 376 | 10,664
'- <class> com.informix.jdbc.IfxSqliConnect @ 0x70cd302f8 | 376 | 9,064
--------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------
Xavier Escote
------------------------------
Original Message:
Sent: Thu June 13, 2024 11:58 AM
From: Brian Hughes
Subject: Informix JDBC driver cleanup bug - memory leak
The cleaner thread was introduced way back, before 4.10.JC6 even if I recall. But the ability to turn it off was introduced much later. Currently the default value is 1 thread. The point of this thread was to help with developers who didn't understand they needed to close connections after they used them (think back before try-with-resources feature or web frameworks like Spring were built in java).
My opinion the feature should not ever be enabled if you are using a framework and web servers like Tomcat or Spring to manage connections for you. I would just shut it off since those frameworks ensure connections are correctly closed when needed and pooled when wanted.
The lingering thread is a defect/bug but most of the time you don't even want it running in the first place so that's the easier solution for you I think. Should the default be 0? Probably yes, but unsure if someone will change it. Changing default behavior is always a tricky subject.
Hope this helps!
------------------------------
Brian Hughes
Original Message:
Sent: Thu June 13, 2024 03:45 AM
From: Markus Holzbauer
Subject: Informix JDBC driver cleanup bug - memory leak
I think the feature is available since JDBC 4.10.JC12. Maybe someone from IBM can correct me...
Cheers,
Markus
------------------------------
Markus Holzbauer
Original Message:
Sent: Thu June 13, 2024 03:40 AM
From: Øyvind Gjerstad
Subject: Informix JDBC driver cleanup bug - memory leak
From which version of the JDBC driver are these connection cleaner threads used?
------------------------------
Øyvind Gjerstad
Developer/Architect
PostNord AS
Original Message:
Sent: Thu June 13, 2024 03:27 AM
From: Markus Holzbauer
Subject: Informix JDBC driver cleanup bug - memory leak
Hello Kristian,
The connection cleaner thread has following properties:
IFMXCONNECTION_CLEANER_THREADS (defaults to 0)
IFMXCONNECTION_CLEANER_DELAY_MAXIMUM (defaults to 15000 msec/15 sec)
You can try to disalbe the connection cleaner thread with following Parameter in the connection string/URL:
;IFMXCONNECTION_CLEANER_THREADS=0
HTH,
Cheers,
Markus
------------------------------
Markus Holzbauer
Original Message:
Sent: Tue June 11, 2024 05:25 AM
From: Kristian Arlt
Subject: Informix JDBC driver cleanup bug - memory leak
I have a problem when hot deploying our Java service to Tomcat, when the app is restarted getting the following WARNING:
07-Jun-2024 14:18:12.815 WARNING [Catalina-utility-1] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [dashboard] appears to have started a thread named [IfxSqliConnectCleaner-Thread-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
java.base/jdk.internal.misc.Unsafe.park(Native Method)
java.base/java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:269)
java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:1758)
java.base/java.util.concurrent.DelayQueue.poll(DelayQueue.java:305)
java.base/java.util.concurrent.DelayQueue.poll(DelayQueue.java:100)
com.informix.jdbc.IfxSqliConnect$IfxSqliConnectCleaner.run(IfxSqliConnect.java:645)
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
java.base/java.lang.Thread.run(Thread.java:1583)
This can be reproduced by consecutive WAR deployments, so that the memory usage increases after each time the service is restarted.
I was wondering if the JDBC driver could be enhanced to help close all resources.
------------------------------
Kristian Arlt
------------------------------