Literały ciągów nie są przechowywane na stosie. Nigdy. W rzeczywistości na stosie nie są przechowywane żadne obiekty.
Literały ciągów znaków (lub dokładniej, obiekty, które je reprezentują String) są historycznie przechowywane w stercie zwany „PermGen” sterty. (Permgen to skrót od permanentnego generowania).
W normalnych okolicznościach literały String i wiele innych rzeczy w stercie permgen jest „trwale” osiągalne i nie są zbierane jako śmieci. (Na przykład literały ciągów są zawsze dostępne z obiektów kodu, które ich używają). Można jednak skonfigurować maszynę JVM tak, aby próbowała znaleźć i zebrać klasy ładowane dynamicznie, które nie są już potrzebne, co może spowodować, że literały String zostaną wyrzucone do pamięci. .
WYJAŚNIENIE # 1 - Nie mówię, że Permgen nie otrzymuje GC. Dzieje się tak, zazwyczaj gdy maszyna JVM decyduje się na uruchomienie pełnego GC. Chodzi mi o to, że literały String będą osiągalne tak długo, jak długo kod, który ich używa, będzie osiągalny, a kod będzie osiągalny tak długo, jak długo jest osiągalny moduł ładujący klasy kodu, a dla domyślnych klas ładujących oznacza to „na zawsze”.
WYJAŚNIENIE # 2 - W rzeczywistości Java 7 i nowsze wersje używają zwykłej sterty do przechowywania puli ciągów. W ten sposób obiekty String, które reprezentują literały String i łańcuchy intern'd, znajdują się w rzeczywistości w zwykłej stercie. (Zobacz odpowiedź @ assylias, aby uzyskać szczegółowe informacje).
Ale wciąż próbuję znaleźć cienką linię między przechowywaniem literału ciągu i ciągu utworzonego za pomocą new
.
Nie ma „cienkiej linii”. To naprawdę bardzo proste:
String
obiekty, które reprezentują / odpowiadają literałom ciągów, są przechowywane w puli ciągów.
String
obiekty utworzone przez String::intern
wywołanie są przechowywane w puli ciągów.
- Wszystkie inne
String
przedmioty NIE są trzymane w puli strun.
Następnie pojawia się oddzielne pytanie, gdzie pula ciągów jest „przechowywana”. Przed Java 7 był to stos permgen. Od wersji Java 7 jest to główna kupa.