2013-04-27 11 views
12

Una parte fondamentale del contratto Java Object è che il metodo hashCode() deve essere coerente con il metodo equals(). Questo ha senso ed è facile da capire: se due oggetti sono "uguali" in qualche modo, dovrebbero restituire lo stesso codice hash. In caso contrario, è possibile inserire un oggetto in un HashSet, ad esempio, e successivamente verificare se un'istanza separata è nell'insieme e in modo errato tornare false, anche se il metodo equals() avrebbe considerato gli oggetti equivalenti.Come ottenere il riconoscimento del bug hashCode() URI Java che è stato negato in modo inappropriato

In realtà il codice URI di Java ha questo problema di Java 6. Prova di questo codice:

import static org.hamcrest.CoreMatchers.*; 
import static org.junit.Assert.*; 

import java.net.URI; 

import org.junit.Test; 

public class URITest 
{ 

    @Test 
    public void testURIHashCode() 
    { 
     final URI uri1 = URI.create("http://www.example.com/foo%2Abar"); 
     final URI uri2 = URI.create("http://www.example.com/foo%2abar"); 
     assertThat("URIs are not equal.", uri1, equalTo(uri2)); 
     assertThat("Equal URIs do not have same hash code.", uri1.hashCode(), equalTo(uri2.hashCode())); 
    } 
} 

URI sequenze di escape, come da RFC 3968, sono case insensitive; ovvero, %2A e %2a sono considerati equivalenti. L'implementazione Java URI.equals() ne tiene conto. Tuttavia, l'implementazione URI.hashCode() fa non tenerne conto! Ciò significa che due istanze URI che restituiscono true per URI.equals() tuttavia possono restituire diversi codici hash, come illustrato nel codice sopra!

Ho inviato questo problema, che presumibilmente si traduce in Java Bug 7134993, ma quell'errore non è più disponibile. Lo stesso problema, tuttavia, viene mostrato in Java Bug 7054089. (Non sono sicuro che ciò sia dovuto alla mia sottomissione o da qualcun altro, ma il problema è lo stesso.) Tuttavia, il bug è stato negato con la valutazione, "Gli esempi citati sono URI opachi e quindi le parti specifiche dello schema sono non analizzato. "

Chiunque abbia valutato questo errore non deve avere familiarità con ciò che significa per equals() e hashCode() per essere coerente. Il contratto per Object.equals() indica chiaramente "Se due oggetti sono uguali in base al metodo equals (Object), quindi chiamare il metodo hashCode su ciascuno dei due oggetti deve produrre lo stesso risultato intero." Nota l'uso di "must", non "dovrebbe".

Il punto qui è che, anche se il valutatore afferma che l'URI è "opaco" e "non analizzato", l'implementazione di URI.equals() (contrariamente alle sue affermazioni) sta effettivamente analizzando l'URI e prendendo in considerazione l'insensibilità del maiuscolo/minuscolo . L'implementazione URI.hashCode() non lo è.

Quindi sono completamente assurdo qui e manca qualcosa di ovvio? Se lo sono, qualcuno per favore mi illumini riguardo al mio errore e segnerò la tua risposta come corretta. Altrimenti, la domanda è: ora che Sun/Oracle non sembra più consentire commenti su bug archiviati, che procedura devo ottenere per ottenere riconoscimento e azione su questo problema fondamentale nell'implementazione Java dell'identificatore primario di Internet, l'URI?

+0

* "quale ricorso è necessario ottenere riconoscimento e azione su questo problema fondamentale (?)" * Un'opzione potrebbe essere quella di richiedere un ticket di supporto con Oracle. Nota che costerà soldi, e comunque potrebbe non risultare in una 'correzione' come la vedi tu. –

+2

Guardando il [codice sorgente java.net.URI] (http://javasourcecode.org/html/open-source/jdk/jdk-6u23/java/net/URI.java.html) il problema è che gli uguali metodo chiama un metodo chiamato equal che annulla in modo specifico le sequenze codificate in percentuale in lettere minuscole, ma il metodo hashCode chiama un metodo hash che fa semplicemente un hash di sequenza di caratteri di base sulla stringa fornita e non fa alcuno sforzo per cercare la percentuale codificata sequenze. È sicuramente un errore da parte di Sun/Oracle. Immagino che la tua unica soluzione sia quella di controllare attentamente l'URI per questo manualmente. – Bobulous

risposta

2

Buone notizie! Oracle sembra aver corretto questo bug per Java 8 in JDK-7171415! Ho verificato che il mio test sopra ora passi in Java 1.8.0_92 su Windows 10 Pro 64-bit. Il nuovo bug non fa riferimento a nessuno dei precedenti, quindi non so come sia successo. Ma sono contento che finalmente l'abbiano risolto.

4

Vorrei inviare nuovamente un errore a Java 1.7.0_17 utilizzando l'esempio che si fornisce qui anziché quello nell'errore 7054089. Ho verificato che l'esempio di StackOverflow contenga anche quella versione. Ho saputo che Oracle ha chiuso bug fixing su Java 6 tranne che per problemi di sicurezza.

Nella sottomissione del bug originale, gli URI che hai fornito sono URI opachi e questo potrebbe aver gettato il valutatore su off. E penso che vuoi dire RFC 2396.

Inoltre, si potrebbe ottenere un valutatore fresca :)

mi sembra che essi hanno definitivamente rotto il contratto per hashCode() qui.

Ed è un peccato che non hanno uno StackOverflow come meccanismo di commento per Java (o le osservazioni di principio come avevano in passato.)

Problemi correlati