When analyzing a heap dump of my application I noticed 1478 instances of java.lang.red.Finalizer class. 501 of them was referencing org.postgresql.jdbc.PgConnection class and another 501 sun.security.ssl.SSLSocketImpl. The length of the queue in Finalizer class is 0.
The up time of the application the heap dump belonged to was 185 hours.
The configuration of db connection pool looks as follows:
- maximum pool size - 5
- max life time - 30 minutes
DB connections expires when are not used for certain time and new are created when needed. So far so good. The workload on the application changes overtime. Also the number of open connections on db size looks good - 5.
When I compare the number of PgConnection instances in heap dumps taken after different up time I see that it increases and the length of the queue in Finalizer class is always 0.
I made a test locally. Just set the max life time in the pool to a very low number and waited 2 hours. The number of PgConnection instances increased from 5 to 16. All staled connections were closed properly (had a break point in PgConnection#close()). The queue size in Finalizer was 0. After executing full GC using VisualVM the number of PgConnections was reduced to 5 and the PgConnection#finalize() method was called (also set a breakpoint here).
Is it expected/normal behavior that objects with overloaded finalize() method (i.e. PgConnection) are not removed by GC automatically? I know that there is no guarantees when such objects are removed. However, in this case it looks like that none of those objects were removed since the app was started. Maybe I miss something in the GC config? I have the DisableExplicitGC argument set in production environment, but as far as I know it should not do any harm to the regular GC work.