在我的程序中,我需要跟踪打开到某个HTTP服务器的连接列表 – 以便在需要时立即断开它们.
我遇到了以下问题.如果我连接到HTTP服务器,一切都很完美,但如果是HTTPS,则不会从列表中删除连接.它会导致内存泄漏.
例:
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); } } }
如果URL指向“http://www.example.com”,则“删除结果= true”.
但如果URL指向“https://www.example.com”,则“删除结果=假”.
我不明白这种行为.我有一些假设,但不是不确定……
有人可以帮忙吗?
解决方法
简而言之(至少,使用HotSpot JVM 23.7-b01),当URL方案是HTTPS时,我们有conn.equals(conn)== false.
操作remove(Object o)是defined,因为删除元素e使得(o == null?e == null:o.equals(e))(即remove以equals定义).可以预期remove(conn)成功,因为刚刚插入了元素,但由于conn.equals(conn)为false,因此集合实现理解该元素未被包含.
这是一个奇怪的情况,其中equals不反身.从the openjdk implementation开始,原因很明显:HttpsURLConnectionImpl将equals的实现委托给一个内部对象,它不等于包装器.
public class HttpsURLConnectionImpl { protected DelegateHttpsURLConnection delegate; public boolean equals(Object obj) { return delegate.equals(obj); } }