Literais de string não são armazenados na pilha. Nunca. Na verdade, nenhum objeto é armazenado na pilha.
Literais de string (ou mais precisamente, os objetos String que os representam) são armazenados historicamente em um Heap chamado heap "permgen". (Permgen é a abreviação de geração permanente.)
Em circunstâncias normais, os literais String e muitas das outras coisas no heap permgen são "permanentemente" alcançáveis e não são coletados como lixo. (Por exemplo, literais String são sempre alcançáveis a partir dos objetos de código que os utilizam.) No entanto, você pode configurar uma JVM para tentar encontrar e coletar classes carregadas dinamicamente que não são mais necessárias, e isso pode fazer com que literais String sejam coletados como lixo .
ESCLARECIMENTO # 1 - Não estou dizendo que o Permgen não recebe GC. Sim, normalmente quando a JVM decide executar um GC Completo. Meu ponto é que literais de String serão alcançáveis contanto que o código que os usa seja alcançável, e o código será alcançável contanto que o classloader do código seja alcançável, e para os classloaders padrão, isso significa "para sempre".
ESCLARECIMENTO # 2 - Na verdade, o Java 7 e posterior usa o heap regular para conter o pool de strings. Portanto, os objetos String que representam literais String e strings internas estão na verdade no heap regular. (Veja a resposta de @assylias para detalhes.)
Mas ainda estou tentando descobrir a linha tênue entre o armazenamento do literal de string e a string criada com new
.
Não existe uma "linha tênue". Isto é realmente muito simples:
String
objetos que representam / correspondem a literais de string são mantidos no pool de string.
String
objetos que foram criados por um String::intern
chamada são mantidos no string pool.
- Todos os outros
String
objetos NÃO são mantidos no pool de strings.
Depois, há a questão separada de onde o pool de strings está "armazenado". Antes do Java 7, era o heap permgen. Do Java 7 em diante, é o heap principal.