7

In my program I need to track list of opened connections to some HTTP server - in order to disconnect them at once if needed.

I faced the following problem. If I connect to HTTP server everything works perfect, but if to HTTPS, then connections are not removed from the list. It leads to memory leak.

Example:

package test;

import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;

public class Main {

    public static void main(String[] args) {
        try {
            ArrayList<URLConnection> al = new ArrayList<URLConnection>();

            URL url = new URL("http://www.example.com");

            URLConnection conn = url.openConnection();
            al.add(conn);
            System.out.println("Result of removing = " + al.remove(conn));

        } catch (Exception ex) {
            ex.printStackTrace(System.err);
        }
    }
}

If URL points to "http://www.example.com" then "Result of removing = true".

But if URL points to "https://www.example.com" then "Result of removing = false".

I don't understand such a behavior. I have some assumptions, but not not sure...

Can anybody help?

1 Answers1

6

In short (at least, with HotSpot JVM 23.7-b01) we have that conn.equals(conn)==false when the URL scheme is HTTPS.

The operation remove(Object o) is defined as removing an element e such that (o==null ? e==null : o.equals(e)) (i.e. remove is defined in terms of equals). One could expect that remove(conn) succeed, since the element has just been inserted, but since conn.equals(conn) is false, the collection implementation understand that the element is not contained.

This is a strange case where equals is not reflexive. From the openjdk implementation the reason is clear: HttpsURLConnectionImpl delegates the implementation of equals to an internal object, which is not equal to the wrapper.

public class HttpsURLConnectionImpl {
   protected DelegateHttpsURLConnection delegate;
   public boolean equals(Object obj) {
    return delegate.equals(obj);
   }
}
Javier
  • 12,100
  • 5
  • 46
  • 57
  • So, it is really the case of strange behaviour of _equals_... I sent away such explanation because it is really mad... Thanks! BTW, don't you know any other examples of classes with such _equals_ behavior? – Andrew Orlov Feb 26 '13 at 07:31
  • No, indeed I didn't know this one either. The only case of a defective implementation of *equals* that I can recall now is that of java.net.URL (in this case the flaw is about consistency: the equality relation depends on DNS resolution, thus two URL instances might or might not be equal depending on the resolved IP address, but that is a different story). – Javier Feb 26 '13 at 09:46