Boa tarde,
Alguém sabe se o GC faz coleta no Pool de String?
obrigado!
Boa tarde,
Alguém sabe se o GC faz coleta no Pool de String?
obrigado!
Não há nada que impeça ele de fazer isso. Mas o comportamento exato varia de VM para VM.
Mas geralmente, há coleta dentro do Pool?
Por exemplo, tente rodar este programa na JVM da Sun. Você vai ver que a string internada (isto é , posta no pool de strings) é tão suscetível à limpeza pelo GC como qualquer outra, se não houver referências para ela.
import java.util.*;
class GCPoolString {
public static void printMemory (String title) {
Runtime r = Runtime.getRuntime();
System.out.println (title + ": " + "free = " + r.freeMemory() + ", total = " + r.totalMemory() + ", max = " +
r.maxMemory());
}
public static void main(String[] args) {
System.gc();
try { Thread.sleep (3000); } catch (InterruptedException ex) {}
printMemory ("After GC 1");
System.out.println ("Now interning 1M strings in string pool");
// Internando um milhão de strings no string pool
for (int i = 1; i < 1000000; ++i) {
new String ("" + i).intern();
}
printMemory ("After interning 1M strings");
System.gc();
try { Thread.sleep (3000); } catch (InterruptedException ex) {}
printMemory ("After GC 2");
System.out.println ("Now interning 1M strings in string pool and keeping a reference to each string");
List<String> list = new ArrayList<String>();
for (int i = 1; i < 1000000; ++i) {
list.add (new String ("" + i).intern());
}
printMemory ("After interning 1M strings and keeping a reference to each one");
System.gc();
try { Thread.sleep (3000); } catch (InterruptedException ex) {}
printMemory ("After GC 3");
System.out.println ("Now removing the reference to the interned strings");
list.clear(); list = null;
try { Thread.sleep (3000); } catch (InterruptedException ex) {}
printMemory ("After removing the reference...");
System.gc();
try { Thread.sleep (3000); } catch (InterruptedException ex) {}
printMemory ("After GC 4");
}
}
Ok, mas volto a dizer que esse comportamento é específico de implementação e não é, em hipótese alguma, obrigatório.
E é por isso que indiquei que era para rodar o meu programa em uma JVM da Sun. Se for tentar rodar o mesmo programa em outra JVM não deve obter o mesmo resultado.
Sim, eu sei, mas não custa reforçar e reforçar…
Contar com isso é, como dizemos em C++, contar com o “realm of undefined behavior”.
Rodei em algumas plataformas:
Windows XP - SP3 - 3 gb RAM:
jdk 1.5_16 - SUN
After GC 1: free = 1912600, total = 2031616, max = 66650112
Now interning 1M strings in string pool
After interning 1M strings: free = 1508176, total = 2031616, max = 66650112
After GC 2: free = 1913568, total = 2031616, max = 66650112
Now interning 1M strings in string pool and keeping a reference to each string
After interning 1M strings and keeping a reference to each one: free = 3097928, total = 7696384, max = 66650112
After GC 3: free = 3557136, total = 7696384, max = 66650112
Now removing the reference to the interned strings
After removing the reference...: free = 3557136, total = 7696384, max = 66650112
After GC 4: free = 7578456, total = 7696384, max = 66650112
IBM - AIX -
jdk: Java™ 2 Runtime Environment, Standard Edition (build pap64dev-20080315 (SR7))
IBM J9 VM (build 2.3, J2RE 1.5.0 IBM J9 2.3 AIX ppc64-64 j9vmap6423-20080315 (JIT enabled)
Mal rodou:
After GC 1: free = 3569752, total = 4194304, max = 67108864
Now interning 1M strings in string pool
After interning 1M strings: free = 2537312, total = 4194304, max = 67108864
After GC 2: free = 3703400, total = 4194304, max = 67108864
Now interning 1M strings in string pool and keeping a reference to each string
Exception:
JVMDUMP013I Processed Dump Event "systhrow", detail "java/lang/OutOfMemoryError".
Exception in thread "main" java.lang.OutOfMemoryError
at java.lang.String.intern(Native Method)
at GCPoolString.main(GCPoolString.java:30)
Estorou a heap
Windows XP - SP3 - 3 gb RAM:
jdk: Bea JRockit - 1.5.12
After GC 1: free = 54533416, total = 67108864, max = [telefone removido]
Now interning 1M strings in string pool
After interning 1M strings: free = 30064640, total = 67108864, max = [telefone removido]
After GC 2: free = 48939008, total = 67108864, max = [telefone removido]
Now interning 1M strings in string pool and keeping a reference to each string
After interning 1M strings and keeping a reference to each one: free = 15618048, total = 107487232, max = [telefone removido]
After GC 3: free = 16207872, total = 107487232, max = [telefone removido]
Now removing the reference to the interned strings
After removing the reference...: free = 16207872, total = 107487232, max = [telefone removido]
After GC 4: free = 16207872, total = 107487232, max = [telefone removido]
Interessante que rodando pela JRE da bea foi mais rápido que jdk da sun…
Rodei o programa e na minha JVM o GC fez bem seu trabalho!
Então, existe coleta dentro de um pool de strings mas depende da implementação da JVM!
Muito obrigado pelas respostas. 