2013-02-26 10 views
7

Nel mio programma ho bisogno di tenere traccia dell'elenco delle connessioni aperte ad alcuni server HTTP - per scollegarli in una volta sola se necessario.Rimozione dell'oggetto URLConnection da ArrayList <URLConnection>

Ho affrontato il seguente problema. Se mi collego al server HTTP, tutto funziona perfettamente, ma se su HTTPS, le connessioni non vengono rimosse dall'elenco. Porta alla perdita di memoria.

Esempio:

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

Se URL punta a "http://www.example.com", quindi "Risultato di rimozione = true".

Ma se l'URL punta a "https://www.example.com", quindi "Risultato di rimozione = falso".

Non capisco un simile comportamento. Ho alcune ipotesi, ma non sono sicuro ...

Qualcuno può aiutare?

risposta

6

In breve (almeno con HotSpot JVM 23.7-b01) abbiamo lo conn.equals(conn)==false quando lo schema URL è HTTPS.

L'operazione remove(Object o) è defined quanto elimina un elemento e tale che (o==null ? e==null : o.equals(e)) (cioè rimuovere è definita in termini di uguale). Ci si potrebbe aspettare che remove (conn) abbia successo, poiché l'elemento è stato appena inserito, ma dal momento che conn.equals(conn) è false, l'implementazione della raccolta capisce che l'elemento non è contenuto.

Questo è uno strano caso in cui è uguale a non è riflessivo. Da the openjdk implementation la ragione è chiara: HttpsURLConnectionImpl delega l'implementazione di uguale a a un oggetto interno, che è non uguale a nel wrapper.

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

Quindi, è davvero il caso di strano comportamento di _equals _... Ho mandato via questa spiegazione perché è davvero pazza ... Grazie! A proposito, non conosci altri esempi di classi con questo comportamento _equals_? –

+0

No, anzi non lo conoscevo neanche io. L'unico caso di un'implementazione difettosa di * uguale a * che posso ricordare ora è quello di java.net.URL (in questo caso il difetto riguarda la coerenza: la relazione di uguaglianza dipende dalla risoluzione DNS, quindi due istanze URL potrebbero o meno essere uguale a seconda dell'indirizzo IP risolto, ma questa è una storia diversa). – Javier

+0

Ora è tutto chiaro. Grazie! –