FIX: Connection Leak Using Parameterized Command In ADO

This article was previously published under Q247757
This article has been archived. It is offered "as is" and will no longer be updated.
When using Windows Foundation Classes for Java (WFC) and ADO, and openinga recordset using a parameterized command object, connections that areproperly closed are not properly pooled and recycled, resulting inleaked connections.To work around this problem, call System.gc() after closing the ADO connection inyour Java COM object. In normal situations, you do not need to call System.gc()after closing an ADO connection in order to free the connection.
This problem is fixed in the latest service packs for Windows 2000 and MDAC 2.5.
  • To resolve this problem, obtain the latest service pack for Windows 2000. For additional information, click the following article number to view the article in theMicrosoft Knowledge Base:
    260910 How to Obtain the Latest Windows 2000 Service Pack
  • To resolve this problem, obtain the latest service pack for Microsoft Data Access Components 2.5. For additional information, click the following article number to view the article in theMicrosoft Knowledge Base:
    293312 INFO: How to Obtain the Latest MDAC 2.5 Service Pack
The English version of this fix should have the following file attributes or later:
File name       Date        Size      Version      -----------------------------------------------------Msado15.dll     1/26/2000   329KB     2.12.4926.0				
Microsoft has confirmed that this is a problem in Microsoft Data Access Objects2.1 SP2 and 2.5. This problem was first corrected in Microsoft Data Access Components 2.5 Service Pack 2 and Microsoft Windows 2000 Service Pack 2.
This connection/session pooling issue occurs when all of the following conditions are present:
  1. Microsoft Data Access Objects 2.1 SP2 is installed.
  2. A parameterized ADO Command object is used.
  3. The Java COM object is hosted in MTS or COM+.
  4. The Java COM object creates a disconnected recordset.

Steps to Reproduce the Behavior

  1. Create a Java COM object project named ConnLoss with Visual J++ 6.0 using the following code:
    import*;public class ConnLoss{  // Modify this connection string to point to a running SQL Server.  private static String m_connect =     "Provider=SQLOLEDB;Server=(Local);Database=Pubs;UID=sa;PWD=;";  public     FindAuthorsLastName( String au_id, boolean fCallGC )  {    Connection conn = null;    Command cmd   = null;    Recordset rs  = null;    try    {           // Open connection to SQL Server.      conn = new Connection();      conn.setCursorLocation( AdoEnums.CursorLocation.CLIENT ); m_connect );            // Prepare command object.      cmd = new Command();      cmd.setActiveConnection( conn );            cmd.setCommandText( "select au_lname from authors where au_id=?" );          cmd.getParameters().append(         cmd.createParameter( "au_id",                    AdoEnums.DataType.VARCHAR,                   AdoEnums.ParameterDirection.INPUT,                   20, au_id ) );            // Execute command.      rs = cmd.execute();            // Disconnect recordset and close connection.      rs.setActiveConnection( (Connection) null );      conn.close();            // Call gc if requested.      if (fCallGC) System.gc();            // Return disconnected recordset.      return ( rs.getDataSource();          }    catch( AdoException adoEX )    {      // Log errors here.    }    return null;  }}					
  2. Add the Java COM object to MTS or the COM+ package.
  3. Call the Java COM object with the following Microsoft Visual Basic for Applications (VBA) code:
    Sub TestConnLoss()Dim objCL As ObjectDim i As LongDim rs As ADODB.recordset  set objCL = CreateObject("ConnLoss.ConnLoss")  For i = 1 To 100    Set rs = objCL.FindAuthorsLastName("756-30-7391", False)    Debug.Print rs.Fields("au_lname").Value    rs.Close    Set rs = Nothing      Next i    End Sub					
  4. Run Windows NT Performance Monitor on the machine where SQL Server 7.0 is located and monitor User Connections under the SQL Server:General Statistics performance counter.
  5. Run the VBA client code. At this point, 100 user connections are generated by the code as reported by Windows NT Performance Monitor, indicating that the OLE DB session pooling is not working properly for the SQL OLE DB provider used by the Java COM object.

  6. Change the second parameter of FindAuthorsLastName to True in order to activate the System.gc() code.
  7. Stop and restart the MTS or COM+ package.
  8. Run the VBA client code a second time.
At this point only a few user connections are generated by the code, indicating that the OLE DB session pooling is working properly for the SQL OLE DB provider used by the Java COM object when System.gc() is called.

NOTE: Calling System.gc() greatly impacts the performance of the Java COM object, so calling System.gc() in general should be avoided when performance is a consideration. For example, the business object could be coded to only call System.gc() every 10 or 100 method calls to reduce the per method performance impact of calling System.gc(). Also, the use of a parameterized command object could be avoided by hard-coding parameter values into a SQL string and not using parameter tokens as in the above example; this circumvents the issue as well.

Article ID: 247757 - Last Review: 02/28/2014 00:29:42 - Revision: 3.0

Microsoft Data Access Components 2.1 Service Pack 2, Microsoft Data Access Components 2.5, Microsoft Visual J++ 6.0 Standard Edition

  • kbnosurvey kbarchive kbbug kbfix kbmdac250sp2fix kbqfe kbhotfixserver KB247757