7

在我的程序中,我需要跟踪到某些 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 ”,则“删除结果 = false”。

我不理解这样的行为。我有一些假设,但不确定...

有人可以帮忙吗?

4

1 回答 1

6

简而言之(至少,对于 HotSpot JVM 23.7-b01),conn.equals(conn)==false当 URL 方案是 HTTPS 时,我们就有这种情况。

该操作remove(Object o)定义为删除元素e使得(o==null ? e==null : o.equals(e))(即删除是根据equals定义的)。可以预期 remove(conn) 会成功,因为元素刚刚被插入,但是因为conn.equals(conn)is false,集合实现理解该元素不包含在内。

这是一个奇怪的情况,其中equals不是自反的。从openjdk 实现来看,原因很清楚:将equalsHttpsURLConnectionImpl的实现委托给一个内部对象,该对象不等于包装器。

public class HttpsURLConnectionImpl {
   protected DelegateHttpsURLConnection delegate;
   public boolean equals(Object obj) {
    return delegate.equals(obj);
   }
}
于 2013-02-26T06:15:29.997 回答