Vejledning til Java String Pool

1. Oversigt

Det Snor objekt er den mest anvendte klasse på Java-sproget.

I denne hurtige artikel udforsker vi Java String Pool - det specielle hukommelsesområde hvor Strenge gemmes af JVM.

2. String Interning

Takket være Strenge i Java kan JVM optimere mængden af ​​hukommelse, der er allokeret til dem af lagring kun en kopi af hver bogstavelig Snor i poolen. Denne proces kaldes praktikant.

Når vi opretter en Snor variabel og tildele den en værdi, søger JVM i puljen efter en Snor af samme værdi.

Hvis den findes, returnerer Java-kompilatoren simpelthen en reference til sin hukommelsesadresse uden at tildele yderligere hukommelse.

Hvis den ikke findes, føjes den til puljen (interneret), og dens reference returneres.

Lad os skrive en lille test for at bekræfte dette:

String constantString1 = "Baeldung"; String constantString2 = "Baeldung"; assertThat (constantString1) .isSameAs (constantString2);

3. Strenge Tildelt ved hjælp af konstruktøren

Når vi opretter en Snor via ny operatør, opretter Java-kompilatoren et nyt objekt og gemmer det i det bunkerum, der er reserveret til JVM.

Hver Snor oprettet som dette vil pege på en anden hukommelsesregion med sin egen adresse.

Lad os se, hvordan dette adskiller sig fra den foregående sag:

String constantString = "Baeldung"; String newString = ny streng ("Baeldung"); assertThat (constantString) .isNotSameAs (newString);

4. Snor Bogstavelig vs. Streng objekt

Når vi opretter en Snor objekt ved hjælp af ny() operatør, opretter det altid et nyt objekt i bunkehukommelse. På den anden side, hvis vi opretter et objekt ved hjælp af Snor bogstavelig syntaks f.eks. "Baeldung", det kan returnere et eksisterende objekt fra strengpoolen, hvis det allerede findes. Ellers opretter det et nyt strengobjekt og placeres i strengpoolen til fremtidig genbrug.

På et højt niveau er begge de Snor objekter, men den største forskel kommer fra det punkt ny() operatør opretter altid en ny Snor objekt. Også når vi opretter en Snor ved hjælp af bogstavelig - det er interneret.

Dette vil være meget mere klart, når vi sammenligner to Snor objekter oprettet ved hjælp af Snor bogstavelig og ny operatør:

String first = "Baeldung"; String anden = "Baeldung"; System.out.println (første == sekund); // Rigtigt

I dette eksempel er Snor objekter vil have den samme reference.

Lad os derefter oprette to forskellige objekter ved hjælp af ny og kontroller at de har forskellige referencer:

String tredje = ny streng ("Baeldung"); Streng fjerde = ny streng ("Baeldung"); System.out.println (tredje == fjerde); // Falsk

Tilsvarende når vi sammenligner a Snor bogstavelig med en Snor objekt oprettet ved hjælp af ny() bruger == operatoren, vender den tilbage falsk:

String femte = "Baeldung"; String sjette = ny streng ("Baeldung"); System.out.println (femte == sjette); // Falsk

Generelt, vi skal bruge Snor bogstavelig notation, når det er muligt. Det er lettere at læse, og det giver kompilatoren en chance for at optimere vores kode.

5. Manuel internering

Vi kan manuelt internere en Snor i Java String Pool ved at ringe til praktikant () metode på det objekt, vi ønsker at praktisere.

Manuelt interning af Snor gemmer sin reference i puljen, og JVM returnerer denne reference, når det er nødvendigt.

Lad os oprette en test case til dette:

String constantString = "interneret Baeldung"; Streng newString = ny streng ("interneret Baeldung"); assertThat (constantString) .isNotSameAs (newString); String internedString = newString.intern (); assertThat (constantString) .isSameAs (internedString);

6. Affaldssamling

Før Java 7, JVM placerede Java String Pool i PermGen plads, som har en fast størrelse - den kan ikke udvides ved kørsel og er ikke berettiget til affaldsindsamling.

Risikoen for interning Strenge i PermGen (i stedet for Bunke) er det vi kan få en Ikke mere hukommelse fejl fra JVM, hvis vi praktiserer for mange Strenge.

Fra Java 7 og fremefter er Java String Pool gemt i Bunke plads, som er indsamlet skrald af JVM. Fordelen ved denne tilgang er reduceret risiko for Ikke mere hukommelse fejl fordi ikke henvist Strenge fjernes fra puljen og frigiver derved hukommelse.

7. Ydeevne og optimeringer

I Java 6 er den eneste optimering, vi kan udføre, at øge PermGen plads under programopkald med MaxPermSize JVM-mulighed:

-XX: MaxPermSize = 1G

I Java 7 har vi mere detaljerede muligheder for at undersøge og udvide / reducere poolstørrelsen. Lad os se de to muligheder for at se poolstørrelsen:

-XX: + PrintFlagsFinal
-XX: + PrintStringTableStatistics

Hvis vi vil øge poolstørrelsen i form af spande, kan vi bruge StringTableSize JVM-mulighed:

-XX: StringTableSize = 4901

Før Java 7u40 var standardpuljestørrelsen 1009 spande, men denne værdi var underlagt nogle få ændringer i nyere Java-versioner. For at være præcis var standardpoolstørrelsen fra Java 7u40 indtil Java 11 60013, og nu steg den til 65536.

Bemærk, at en forøgelse af poolstørrelsen vil forbruge mere hukommelse, men har fordelen ved at reducere den tid, det tager at indsætte Strenge ind i bordet.

8. En note om Java 9

Indtil Java 8, Strenge var internt repræsenteret som en række tegn - char [], kodet i UTF-16, så hvert tegn bruger to byte hukommelse.

Med Java 9 leveres en ny repræsentation, kaldet Kompakte strenge. Dette nye format vælger den passende kodning imellem char [] og byte [] afhængigt af det gemte indhold.

Siden den nye Snor repræsentation vil bruge UTF-16 kodning kun, når det er nødvendigt, mængden af bunke hukommelsen vil være betydeligt lavere, hvilket igen medfører mindre Skraldemand overhead på JVM.

9. Konklusion

I denne vejledning viste vi, hvordan JVM og Java-compileren optimerer hukommelsestildelinger til Snor objekter via Java String Pool.

Alle kodeeksempler, der bruges i artiklen, er tilgængelige på GitHub.