Questo è un bell'articolo che delinea due ragioni già menzionate nelle risposte sopra:
- Sicurezza : il sistema può distribuire parti sensibili di informazioni di sola lettura senza preoccuparsi che vengano modificate
- Prestazioni : i dati immutabili sono molto utili per rendere le cose sicure per i thread.
E questo è probabilmente il commento più dettagliato in quell'articolo. Ha a che fare con il pool di stringhe in Java e problemi di sicurezza. Riguarda come decidere cosa va nel pool di stringhe. Supponendo che entrambe le stringhe siano uguali se la loro sequenza di caratteri è la stessa, allora abbiamo una condizione di competizione su chi arriva prima e insieme ai problemi di sicurezza. In caso contrario, il pool di stringhe conterrà stringhe ridondanti, perdendo così il vantaggio di averlo in primo luogo. Leggilo per te, vero?
L'estensione della stringa avrebbe causato il caos con uguali e stagisti. JavaDoc afferma che è uguale a:
Confronta questa stringa con l'oggetto specificato. Il risultato è vero se e solo se l'argomento non è null ed è un oggetto String che rappresenta la stessa sequenza di caratteri di questo oggetto.
Supponendo che java.lang.String
non fosse definitivo, a SafeString
potrebbe eguagliare a String
e viceversa; perché rappresenterebbero la stessa sequenza di personaggi.
Cosa succederebbe se ti applicassi intern
a SafeString
- andrebbe SafeString
nel pool di stringhe della JVM? L' ClassLoader
e tutti gli oggetti i SafeString
riferimenti in attesa per gli aspiranti quindi ottenere bloccato in posizione per tutta la durata della JVM. Avresti una condizione di gara su chi potrebbe essere il primo a internare una sequenza di personaggi - forse SafeString
vinceresti, forse un String
, o forse un SafeString
carico da un caricatore di classi diverso (quindi una classe diversa).
Se vincessi la gara in piscina, questo sarebbe un vero singleton e le persone potrebbero accedere al tuo intero ambiente (sandbox) attraverso la riflessione e secretKey.intern().getClass().getClassLoader()
.
Oppure la JVM potrebbe bloccare questo buco assicurandosi che solo oggetti String concreti (e nessuna sottoclasse) siano stati aggiunti al pool.
Se equals è stato implementato in modo tale che SafeString
! = String
Then SafeString.intern
! = String.intern
, E SafeString
dovrebbe essere aggiunto al pool. Il pool diventerebbe quindi un pool <Class, String>
anziché anziché <String>
e tutto ciò di cui avresti bisogno per entrare nel pool sarebbe un nuovo classloader.