Літеральні рядки не зберігаються у стеку. Ніколи. Насправді жодних об’єктів не зберігається у стеку.
Рядкові літерали (або , точніше, об'єкти рядків , які представляють їх) є історично зберігаються в Heap називається «PermGen» купа. (Пермген короткий для постійного покоління.)
За звичайних обставин, рядкові літерали та значна частина інших речей в купі пермгену "постійно" доступні і не збираються сміттям. (Наприклад, рядкові літерали завжди доступні від об'єктів коду, які їх використовують.) Однак ви можете налаштувати JVM для пошуку та збору динамічно завантажених класів, які більше не потрібні, і це може призвести до того, що рядкові рядки збираються сміттям .
ПОЯСНЕННЯ №1 - Я не кажу, що Пермген не отримує GC'ed. Це, як правило, коли JVM вирішує запустити Full GC. Моя думка полягає в тому, що рядкові літерали будуть доступні до тих пір, поки код, який їх використовує, буде доступний, і код буде доступний до тих пір, поки завантажувач класів коду буде доступний, а для завантажувачів класів за замовчуванням це означає "назавжди".
ПОЯСНЕННЯ №2 - Насправді Java 7 і пізніші версії використовує звичайну купу для утримання пулу рядків. Таким чином, об'єкти String, які представляють літеральні рядки та рядки intern'd, фактично знаходяться у звичайній купі. (Детальніше див. У відповіді @ assylias.)
Але я все ще намагаюся з'ясувати тонку межу між зберіганням рядка-літералу та рядком, створеним за допомогою new
.
Немає «тонкої лінії». Це дійсно дуже просто:
String
об'єкти, які представляють / відповідають літеральним рядкам, зберігаються в пулі рядків.
String
об'єкти, створені String::intern
викликом, зберігаються в пулі рядків.
- Усі інші
String
об'єкти НЕ утримуються у пулі рядків.
Тоді виникає окреме питання про те, де "зберігається" рядок рядків. До Java 7 це була купа пермгенів. Від Java 7 це головна купа.