Removing a URLConnection Object from an ArrayList <URLConnection>
In my program, I need to keep track of the list of open connections on some kind of HTTP server - in order to disconnect them immediately if necessary.
I had the following problem. If I connect to the HTTP server, everything works fine, but if HTTPS, then the connections are not removed from the list. This causes a 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 the URL points to " http://www.example.com ", then "Delete result = true".
But if the URL points to " https://www.example.com ", then "Delete result = false".
I do not understand this behavior. I have some assumptions, but not sure ...
Does anyone help?
In short (at least with HotSpot JVM 23.7-b01), we have conn.equals(conn)==false when the URL scheme is HTTPS.
The remove(Object o) operation is defined as deleting an element e such that (o==null ? e==null : o.equals(e)) (i.e. remove is defined in equal terms). One would expect that remove (conn) would succeed because the element has just been inserted, but since conn.equals(conn) is false , the collection implementation understands that the element is not contained.
This is a strange case when equals are not reflective. From the openjdk implementation, the reason is clear: HttpsURLConnectionImpl delegates the implementation to an internal object that is not equal to the wrapper.
public class HttpsURLConnectionImpl { protected DelegateHttpsURLConnection delegate; public boolean equals(Object obj) { return delegate.equals(obj); } }