Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Removing URLConnection object from ArrayList<URLConnection>

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?

like image 501
Andrew Orlov Avatar asked Feb 26 '13 06:02

Andrew Orlov


1 Answers

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);
   }
}
like image 101
Javier Avatar answered Nov 15 '22 11:11

Javier