GC e String Pool

8 respostas
Marck

Boa tarde,

Alguém sabe se o GC faz coleta no Pool de String?

obrigado!

8 Respostas

ViniGodoy

Não há nada que impeça ele de fazer isso. Mas o comportamento exato varia de VM para VM.

Marck

Mas geralmente, há coleta dentro do Pool?

T

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");
    }
}
ViniGodoy

Ok, mas volto a dizer que esse comportamento é específico de implementação e não é, em hipótese alguma, obrigatório.

T

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.

ViniGodoy

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”.

ramilani12

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…

Marck

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. :smiley:

Criado 15 de dezembro de 2008
Ultima resposta 15 de dez. de 2008
Respostas 8
Participantes 4