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