Удаление объекта URLConnection из ArrayList<URLConnection>
В моей программе мне нужно отслеживать список открытых подключений к какому-либо 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/", то "Результат удаления = ложь".
Я не понимаю такого поведения. У меня есть некоторые предположения, но я не уверен...
Кто-нибудь может помочь?
1 ответ
Короче говоря (по крайней мере, с HotSpot JVM 23.7-b01) мы имеем это conn.equals(conn)==false
когда схема URL HTTPS.
Операция remove(Object o)
определяется как удаление элемента е так, что (o==null ? e==null : o.equals(e))
(т.е. удалить определяется с точки зрения равных). Можно ожидать, что remove (conn) будет успешным, так как элемент был только что вставлен, но так как conn.equals(conn)
является false
, реализация коллекции понимает, что элемент не содержится.
Это странный случай, когда равные не рефлексивны. Из реализации openjdk причина ясна: HttpsURLConnectionImpl
делегирует реализацию equals внутреннему объекту, который не равен оболочке.
public class HttpsURLConnectionImpl {
protected DelegateHttpsURLConnection delegate;
public boolean equals(Object obj) {
return delegate.equals(obj);
}
}