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)==falseURL スキームが HTTPS の場合です。

操作remove(Object o)は、要素eを次のように削除することとして定義されます(つまり、 remove はequalsに関して定義されます)。要素が挿入されたばかりなので、 remove(conn) が成功すると期待できますが、isであるため、コレクションの実装は要素が含まれていないことを理解しています。(o==null ? e==null : o.equals(e))conn.equals(conn)false

これはequalsが再帰的でない奇妙なケースです。openjdk の実装から、その理由は明らかです。equals の実装を、ラッパーとは異なる内部オブジェクトに委譲HttpsURLConnectionImplします。

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