JDK-6522848 : memory leak in 64-bit JVM 1.5.0_09 on RHEL4 U4 with javax.naming.directory.InitialDirContext()
  • Type: Bug
  • Component: core-libs
  • Sub-Component: javax.naming
  • Affected Version: 5.0u11
  • Priority: P2
  • Status: Closed
  • Resolution: Duplicate
  • OS: linux_redhat_4.0
  • CPU: x86
  • Submitted: 2007-02-08
  • Updated: 2022-10-21
  • Resolved: 2007-11-06
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
5.0u9Resolved
Related Reports
Duplicate :  
Description
Small Java program that does repeatedly connect to a directory server
via javax.naming.directory.InitialDirContext() sees a memory leak.
The problem was only reproducible with 64-bit JVM on 64-bit Linux RHEL4 U4 so far.
The problem is only reproducible on multiprocessor hardware.


1. Testcase
-----------
 The problem could be reproduced with the following program: 
 It only iterates over 
   ctx=new InitialDirContext(env);

 Customer's testcase running on new Intel 64-bit processors
 can reproduce the problem also with doing a ctx.search()
 

% more test.java

import java.util.Hashtable;
import javax.naming.directory.InitialDirContext;
import javax.naming.Context;


public class test
{

  public static void main(String[] args) {

    Hashtable env=null;
    String ldapServerName=null;
    String ldapServerPort=null;
    String bindDN=null;
    String bindPassword=null;
    String timeOut=null;
    String debug=null;

    try {              

      ldapServerPort=System.getProperty("port","389");
      ldapServerName=System.getProperty("server","127.0.0.1");
      bindDN="cn=Manager,dc=sun,dc=com";
      bindPassword=System.getProperty("password","secret");

      timeOut=System.getProperty("timeout","3000");

        // Make the context...
      env=new Hashtable();
        // init ldap service
      env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
        // give host and port
      env.put(Context.PROVIDER_URL, "ldap://"+ldapServerName+":"+ldapServerPort);
        // If using anonymous authentication
//      env.put(Context.SECURITY_AUTHENTICATION, "none");
      env.put(Context.SECURITY_AUTHENTICATION, "simple");
      env.put(Context.SECURITY_PRINCIPAL, bindDN);
      env.put(Context.SECURITY_CREDENTIALS, bindPassword);
      env.put("com.sun.jndi.ldap.connect.timeout", timeOut);

    }
    catch(Exception ex) {
      System.out.println("Authorisation failed: " +ex);
    }

    InitialDirContext ctx=null;

    while(true) {
      try {
        // open LDAP connection
        ctx=new InitialDirContext(env);
      } catch(Exception ex) {
        System.out.println("InitialDirContext failed: "+ex);
        if (debug != null) ex.printStackTrace();
      } finally {

        try {
          if(ctx != null) { ctx.close(); }
        } catch(Exception ex) {
          System.out.println("ctx.close gave error:"+ex);
        }
        ctx=null;
      } //try
    } //while

  }
}


2. Leak
-------
$ ps -edalf | grep java
0 S tl15687  13666 21989 80  76   0 - 76646 -      08:49 pts/1    00:00:14 jdk1.5.0_11/bin/java -Xmx10m test
$ 
 running over the weekend:
$ ps -edalf | grep java
0 S tl15687  11532     1 38  77   0 - 85607 -      Feb02 ?        1-01:53:51 jdk1.5.0_11/bin/java -Xmx10m test
$ 

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                               
13666 tl15687   17   0  299m  40m 9368 S   34  0.5   0:28.39 java    

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                               
11532 tl15687   20   0  334m  79m 9396 S   34  1.0   1554:03 java    



3. additional information
-------------------------
 The leak seems to be dependant of exceptions. 
 One exception that is strictly associated with the leak is the following:

InitialDirContext failed: javax.naming.CommunicationException: 127.0.0.1:389 [Root exception is java.net.ConnectException: Cannot assign requested address]

 This expands to the following:

InitialDirContext failed: javax.naming.CommunicationException: 127.0.0.1:389 [Root exception is java.net.ConnectException: Cannot assign requested address]
javax.naming.CommunicationException: 127.0.0.1:389 [Root exception is java.net.ConnectException: Cannot assign requested address]
        at com.sun.jndi.ldap.Connection.<init>(Connection.java:194)
        at com.sun.jndi.ldap.LdapClient.<init>(LdapClient.java:118)
        at com.sun.jndi.ldap.LdapClient.getInstance(LdapClient.java:1578)
        at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2596)
        at com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:283)
        at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:175)
        at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:193)
        at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:136)
        at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:66)
        at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:667)
        at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:247)
        at javax.naming.InitialContext.init(InitialContext.java:223)
        at javax.naming.InitialContext.<init>(InitialContext.java:197)
        at javax.naming.directory.InitialDirContext.<init>(InitialDirContext.java:82)
        at test.main(test.java:115)
Caused by: java.net.ConnectException: Cannot assign requested address
        at java.net.PlainSocketImpl.socketConnect(Native Method)
        at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)
        at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)
        at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182)
        at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)
        at java.net.Socket.connect(Socket.java:516)
        at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:585)
        at com.sun.jndi.ldap.Connection.createSocket(Connection.java:333)
        at com.sun.jndi.ldap.Connection.<init>(Connection.java:181)
        ... 14 more

 On Solaris I could not reproduce the problem. I see exceptions as well,
 but not the "java.net.ConnectException: Cannot assign requested address"
 exceptions. 
 On Solaris, we have:
InitialDirContext failed: javax.naming.CommunicationException: 10.16.54.104:489 [Root exception is java.net.SocketTimeoutException: connect timed out]

 We were unable to see a memory leak on Solaris with this 
 "java.net.SocketTimeoutException: connect timed out" exception.

Comments
EVALUATION It finally turned out that the problem described here is no longer reproducible using 1.5.0_12 build02, while it is still reproducible using 1.5.0_12 build01. This strongly suggests that we have encountered bug 6502317 hotspot compiler2 Deoptimization code of Java 1.5.x looks leaking memory. which was fixed in 1.5.0_12 build02. The problem also does no longer appear in 1.6.0_02, while it is still there in 1.6.0_01. Bug # 6502317 was fixed in 1.6.0_02 build01. More evidence for a duplicate of 6502317: - only server VM is affected - a native memory leak is produced - is reproducible on Linux I strongly suggest closing this bug as a duplicate of 6502317.
02-11-2007

EVALUATION While we carry on the investigation on the memory leak, I am wondering if the customer's production environment is using Connection Pooling mechanism provided by JNDI. Connection Pooling allows sharing of connections resulting in reduction in resource consumption of an LDAP application. Information about Connection Pooling can be found at: http://java.sun.com/docs/books/tutorial/jndi/ldap/pool.html Connection pooling can be enabled with addtion of a single line to the source code: // Enable connection pooling env.put("com.sun.jndi.ldap.connect.pool", "true");
23-02-2007