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?
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);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With