Issue Details (XML | Word | Printable)

Key: JDBC-249
Type: Bug Bug
Status: Closed Closed
Resolution: Fixed
Priority: Major Major
Assignee: Mark Rotteveel
Reporter: Alexey Kovyazin
Votes: 0
Watchers: 1
Operations

If you were logged in you would be able to see more operations.
Jaybird JCA/JDBC Driver

Memory leak while getting multiple connections with the same parameters

Created: 20/Apr/12 05:41 PM   Updated: 18/Aug/12 07:31 AM
Component/s: JDBC driver
Affects Version/s: Jaybird 2.2
Fix Version/s: Jaybird 2.2


 Description  « Hide
Currently to generate key for hash table of FBConnectionProperties field "mapper" is used. This field is being lazy initialized during the first getMapper() call.
So after the first such call hash key became different from stored, equals() gives the false result and another copy of FBConnectionProperties is added.
Getting new connection with the same URL and properties makes hash table to grow infinitely.
There is few bytes leak per connection, but this became critical after 20-30 thousands of connects/disconnects.

public class DriverTest {

   protected static final int CONNECTIONS_COUNT = 1000000;

   @Test
   public void createManyConnectionsWithSameProperties() throws Exception {
       new FBDriver();
       final Runtime rt = Runtime.getRuntime();
       for ( int i = 0; i < CONNECTIONS_COUNT; i++ ) {
           final Connection connection = DriverManager.getConnection(
                   "jdbc:firebirdsql:localhost/3050:/Library/Frameworks/Firebird.framework/Versions/Current/Resources/examples/empbuild/employee.fdb",
                   "SYSDBA", "masterkey"
           );
           connection.close();
           if ( i % 50 == 0 ) {
               System.gc();
               System.out.printf(""+i
                       +" free mem: %d b\n",
                       rt.freeMemory()
               );
           }
       }
   }
}

 All   Comments   Change History   Subversion Commits      Sort Order: Ascending order - Click to sort in descending order
Mark Rotteveel added a comment - 20/Apr/12 07:45 PM
Where is FBConnectionProperties being used as a key to a Map / HashTable? I quickly scanned to code, but couldn't find it.

Alexey Kovyazin added a comment - 20/Apr/12 08:26 PM
sorry for incomplete description

 FBConnectionProperties is not used as a key, key is instance of FBManagedConnectionFactory mcf
method AbstractDriver.createDataSource

 private FBDataSource createDataSource(FBManagedConnectionFactory mcf) throws ResourceException {
       FBDataSource dataSource = null;
       synchronized (mcfToDataSourceMap)
       {
           dataSource = (FBDataSource)mcfToDataSourceMap.get(mcf);
           
           if (dataSource == null) {
               dataSource = (FBDataSource)mcf.createConnectionFactory();
               mcfToDataSourceMap.put(mcf, dataSource);
           }
       }
       return dataSource;
   }

and FBManagedConnectionFactory in the implementation of equals/hashCode uses FBConnectionProperties.equals/hashCode

Mark Rotteveel added a comment - 21/Apr/12 07:10 AM
It looks like removing mapper from hashCode and equals, and make sure the defaultIsolation is recorded in FBConnectionProperties if it is changed will fix this specific problem.
However I think the hashCode of FBConnectionProperties is inherently unstable: if one of the values recorded in the internal HashMap properties is changed or the value of type, database, tpbMapping or defaultTransactionIsolation is changed. This may require more thinking to get right.

Limiting the hashCode to database and type could be good enough and leave the rest to equals. I will need to research and test this a little bit longer.

Mark Rotteveel added a comment - 21/Apr/12 10:08 AM
Committed fix; I reduced the hashCode calculation to the most stable fields so it should remain stable. Also fixed a potential thread safety issue.

I also changed the storage of mcfToDataSourceMap to a WeakHashMap to prevent a potential different memory leak, but I am not 100% sure if that worked (limited testing did not reveal it getting garbage collected).

Mark Rotteveel added a comment - 21/Apr/12 10:09 AM
Fixed for Jaybird-2.2 after beta-1