Útmutató a Java karakterlánckészlethez
1. Áttekintés
A Húr Az objektum a Java nyelv leggyakrabban használt osztálya.
Ebben a rövid cikkben a Java karakterlánckészletet vizsgáljuk meg - a különleges memória régió, ahol Húrok a JVM tárolja.
2. Vonós internálás
Köszönhetően a Húrok Java-ban a JVM optimalizálni tudja az általuk lefoglalt memória mennyiségét minden literálusból csak egy példányt tárol Húr a medencében. Ezt a folyamatot hívják internáló.
Amikor létrehozunk egy Húr változót és hozzárendel hozzá egy értéket, a JVM a készletben keresi a Húr egyenlő értékű.
Ha megtalálta, a Java fordító egyszerűen visszaad egy hivatkozást a memória címére, anélkül, hogy további memóriát osztana ki.
Ha nem található, hozzáadódik a készlethez (internálva), és referenciáját visszaküldi.
Írjunk egy kis tesztet ennek ellenőrzésére:
String konstansString1 = "Baeldung"; String konstansString2 = "Baeldung"; assertThat (konstansString1) .isSameAs (konstansString2);
3. Húrok Kiosztva a Konstruktor használatával
Amikor létrehozunk egy Húr a új operátor, a Java fordító új objektumot hoz létre, és a JVM számára fenntartott kupacterületen tárolja.
Minden Húr így létrehozva egy másik memóriaterületre mutat, saját címmel.
Lássuk, miben különbözik ez az előző esettől:
String konstansString = "Baeldung"; String newString = új karakterlánc ("Baeldung"); assertThat (konstansString) .isNotSameAs (newString);
4. Húr Szó szerint vs Karakterlánc objektum
Amikor létrehozunk egy Húr objektum a új() operátor, mindig új objektumot hoz létre a kupac memóriában. Másrészt, ha egy objektumot használunk Húr szó szerinti szintaxis pl. „Baeldung”, visszaadhat egy meglévő objektumot a String készletből, ha az már létezik. Ellenkező esetben létrehoz egy új String objektumot, és beteszi a karakterlánc készletbe a későbbi újrafelhasználás céljából.
Magas szinten mindkettő az Húr tárgyakat, de a fő különbség onnan származik, hogy új() operátor mindig létrehoz egy újat Húr tárgy. Továbbá, amikor létrehozunk egy Húr literál használatával - internálják.
Ez sokkal egyértelműbb lesz, ha kettőt hasonlítunk össze Húr használatával létrehozott objektumok Húr szó szerinti és a új operátor:
String first = "Baeldung"; Második karakterlánc = "Baeldung"; System.out.println (első == második); // Igaz
Ebben a példában a Húr az objektumoknak ugyanaz lesz a hivatkozása.
Ezután hozzunk létre két különböző objektumot a használatával új és ellenőrizze, hogy különböző hivatkozások vannak-e:
Harmadik húr = új húr ("Baeldung"); Negyedik húr = új húr ("Baeldung"); System.out.println (harmadik == negyedik); // Hamis
Hasonlóképpen, amikor összehasonlítjuk a Húr szó szerint egy Húr használatával létrehozott objektum új() = = operátor használatával visszatér hamis:
Ötödik húr = "Baeldung"; A hatodik húr = új húr ("Baeldung"); System.out.println (ötödik == hatodik); // Hamis
Általánosságban, használnunk kell a Húr szó szerinti jelölés, ha lehetséges. Könnyebb olvasni, és lehetőséget ad a fordítónak a kódunk optimalizálására.
5. Kézi internálás
Manuálisan internálhatunk a Húr a Java karakterlánckészletben a gyakornok() módszer az objektumon, amelyet internálni akarunk.
A. Manuális internálása Húr tárolja referenciáját a készletben, és a JVM szükség esetén visszaadja ezt a referenciát.
Hozzunk létre egy tesztesetet ehhez:
String constantString = "internált Baeldung"; String newString = új String ("internált Baeldung"); assertThat (konstansString) .isNotSameAs (newString); String internedString = newString.intern (); assertThat (konstansString) .isSameAs (internáltString);
6. Szemétgyűjtés
Java 7 előtt a JVM a Java karakterlánc készletet a PermGen hely, amelynek rögzített mérete van - futás közben nem bővíthető, és nem alkalmas szemétszállításra.
Az internálás kockázata Húrok ban,-ben PermGen (a Halom) az, hogy a kaphatunk egy Elfogyott a memória hiba a JVM-től, ha túl sokat internálunk Húrok.
A Java 7-től kezdődően a Java karakterlánckészlet az tárolja a Halom helyet, ami szemetet gyűjt a JVM által. Ennek a megközelítésnek az előnye az csökkent kockázata Elfogyott a memória hiba mert referálatlan Húrok eltávolításra kerül a készletből, ezáltal felszabadítva a memóriát.
7. Teljesítmény és optimalizálás
A Java 6-ban az egyetlen optimalizálás, amelyet végre tudunk hajtani, a PermGen helyet a programhívás során a MaxPermSize JVM opció:
-XX: MaxPermSize = 1G
A Java 7-ben részletesebb lehetőségeink vannak a medence méretének vizsgálatára és bővítésére / csökkentésére. Nézzük meg a medence méretének megtekintésének két lehetőségét:
-XX: + PrintFlagsFinal
-XX: + PrintStringTableStatistics
Ha növelni akarjuk a medence méretét a vödrök tekintetében, használhatjuk a StringTableSize JVM opció:
-XX: StringTableSize = 4901
A Java 7u40 előtt a készlet alapértelmezett mérete 1009 vödör volt, de ez az érték néhány változáson ment keresztül a legújabb Java verziókban. Pontosabban: az alapértelmezett készlet mérete a Java 7u40-től a Java 11-ig 60013 volt, és most 65536-ra nőtt.
Ne feledje, hogy a készlet méretének növelése több memóriát emészt fel, de előnye, hogy csökkenti a Húrok az asztalba.
8. Megjegyzés a Java 9-ről
Java 8-ig, Húrok belsőleg karakterek tömbjeként képviseltették magukat - char [], kódolva UTF-16, így minden karakter két bájt memóriát használ.
A Java 9 esetén egy új reprezentáció jön létre, az úgynevezett Kompakt húrok. Ez az új formátum kiválasztja a megfelelő kódolást char [] és byte[] a tárolt tartalomtól függően.
Mivel az új Húr képviselet a UTF-16 csak szükség esetén kódolja a mennyiségét halom a memória lényegesen alacsonyabb lesz, ami viszont kevesebbet okoz Szemetes rezsi a JVM.
9. Következtetés
Ebben az útmutatóban megmutattuk, hogyan optimalizálja a JVM és a Java fordító a memóriafoglalásokat Húr objektumok a Java karakterlánckészleten keresztül.
A cikkben használt összes kódminta elérhető a GitHubon.