2013-02-26 8 views
7

W moim programie muszę śledzić listę otwartych połączeń z jakimś serwerem HTTP - w razie potrzeby rozłączyć je natychmiast.Usuwanie obiektu URLConnection z tablicy ArrayList <URLConnection>

Napotkałem następujący problem. Jeśli podłączę się do serwera HTTP, wszystko działa idealnie, ale jeśli do HTTPS, połączenia nie zostaną usunięte z listy. Prowadzi to do wycieku pamięci.

Przykład:

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); 
     } 
    } 
} 

Jeśli adres URL wskazuje na "http://www.example.com", a następnie "Wynik usuwania = true".

Ale jeśli URL wskazuje na "https://www.example.com", to "Wynik usunięcia = fałsz".

Nie rozumiem takiego zachowania. Mam pewne założenia, ale nie jestem pewien ...

Czy ktoś może pomóc?

Odpowiedz

6

W skrócie (przynajmniej z HotSpot JVM 23.7-b01) mamy ten conn.equals(conn)==false, gdy schemat URL jest HTTPS.

Operacja remove(Object o) jest defined jak usuwanie Elementem e tak, że (o==null ? e==null : o.equals(e)) (tj usunąć, jest definiowane równa). Można oczekiwać, że remove (conn) się powiedzie, ponieważ element właśnie został wstawiony, ale od conn.equals(conn) jest false, implementacja kolekcji rozumie, że element nie jest zawarty.

To dziwny przypadek, w którym jest równy nie jest refleksyjny. Od the openjdk implementation powód jest jasny: HttpsURLConnectionImpl deleguje implementację równa się do wewnętrznego obiektu, który jest nie równy do opakowania.

public class HttpsURLConnectionImpl { 
    protected DelegateHttpsURLConnection delegate; 
    public boolean equals(Object obj) { 
    return delegate.equals(obj); 
    } 
} 
+0

Tak, to jest naprawdę przypadek dziwnego zachowania _equals _... Wysłałem takie wyjaśnienie, ponieważ jest naprawdę szalone ... Dzięki! BTW, czy nie znasz innych przykładów klas o takim _równomiernym zachowaniu? –

+0

Nie, w istocie też tego nie znałem. Jedyny przypadek wadliwej implementacji * równa się *, którą teraz mogę sobie przypomnieć, to java.net.URL (w tym przypadku wada dotyczy spójności: relacja równości zależy od rozdzielczości DNS, dlatego dwie instancje URL mogą lub nie być równy w zależności od rozwiązanego adresu IP, ale to już inna historia). – Javier

+0

Teraz wszystko jest jasne. Dzięki! –