Ini adalah artikel yang bagus yang menguraikan dua alasan yang telah disebutkan pada jawaban di atas:
- Keamanan : sistem dapat membagikan bit sensitif informasi hanya baca tanpa khawatir mereka akan diubah
- Performa : data yang tidak dapat diubah sangat berguna dalam membuat hal-hal yang aman.
Dan ini mungkin komentar paling detail dalam artikel itu. Ini ada hubungannya dengan kumpulan string di Jawa dan masalah keamanan. Ini tentang bagaimana memutuskan apa yang masuk ke kolam string. Dengan asumsi kedua string sama jika urutan karakter mereka sama, maka kita memiliki kondisi balapan tentang siapa yang sampai di sana terlebih dahulu dan bersamaan dengan itu masalah keamanan. Jika tidak, maka kumpulan string akan berisi string yang berlebihan sehingga kehilangan keuntungan dari memilikinya di tempat pertama. Bacakan saja sendiri, ya?
Extending String akan memainkan malapetaka dengan equals dan intern. JavaDoc mengatakan equals:
Membandingkan string ini dengan objek yang ditentukan. Hasilnya benar jika dan hanya jika argumennya tidak nol dan merupakan objek String yang mewakili urutan karakter yang sama dengan objek ini.
Dengan asumsi java.lang.String
itu belum final, a SafeString
bisa sama dengan String
, dan sebaliknya; karena mereka mewakili urutan karakter yang sama.
Apa yang akan terjadi jika Anda melamar intern
ke SafeString
- apakah SafeString
masuk ke kumpulan string JVM? The ClassLoader
dan semua objek yang SafeString
referensi diadakan untuk kemudian akan mendapatkan terkunci di tempat untuk seumur hidup dari JVM. Anda akan mendapatkan kondisi balapan tentang siapa yang bisa menjadi orang pertama yang magang serangkaian karakter - mungkin Anda SafeString
akan menang, mungkin a String
, atau mungkin SafeString
dimuat oleh classloader yang berbeda (dengan demikian kelas yang berbeda).
Jika Anda memenangkan perlombaan ke kolam renang, ini akan menjadi singleton sejati dan orang-orang dapat mengakses seluruh lingkungan Anda (kotak pasir) melalui refleksi dan secretKey.intern().getClass().getClassLoader()
.
Atau JVM dapat memblokir lubang ini dengan memastikan bahwa hanya objek String beton (dan tidak ada subkelas) yang ditambahkan ke kumpulan.
Jika persamaan diterapkan sedemikian rupa SafeString
! = String
Maka SafeString.intern
! = String.intern
, Dan SafeString
harus ditambahkan ke kumpulan. Kolam kemudian akan menjadi kolam <Class, String>
bukan <String>
dan semua yang Anda butuhkan untuk memasuki kolam akan menjadi classloader segar.