Salut,
Je dirais que c'est parce que le GC fait bien son boulot tout seul... en libérant la mémoire quand il le faut. Pour cela il utilise deux types de libérations les minors collections et les majors collections (bien plus gourmande en temps). Pour plus d'info :
http://gfx.developpez.com/tutoriel/java/gc/
En appelant explicitement System.gc() on le force à faire le ménage... ce qui peut être pénalisant !
Un exemple : la création de 50000 objets dans un boucle :
1 2 3 4 5
| System.out.println("START");
for (int i = 50000; i>0; i--) {
Object o = new Object();
}
System.out.println("END"); |
Lorsque j'exécute ce code avec l'option
-verboce:gc de la JVM (ce qui permet de logger le passage du GC), j'obtiens ceci :
1 2 3
| START
[GC 512K->102K(1984K), 0.0080338 secs]
END |

Le GC effectue seulement une minor collection qui dure environ 8 millisecondes, et fait descendre la mémoire de 512K à 102k. Le programme s'exécute en quelques ms...
Maintenant si je force le passage du GC à chaque itération :
1 2 3 4 5 6
| System.out.println("START");
for (int i = 50000; i>0; i--) {
Object o = new Object();
System.gc();
}
System.out.println("END"); |
J'obtiens ceci :
1 2 3 4 5 6 7
| START
[Full GC 148K->102K(1984K), 0.0420998 secs]
[Full GC 102K->102K(1984K), 0.0406980 secs]
[Full GC 102K->102K(1984K), 0.0422317 secs]
[Full GC 102K->102K(1984K), 0.0385216 secs]
[Full GC 102K->102K(1984K), 0.0447407 secs]
(...) |
J'ai bien sûr tronqué le résultat, car le programme est très long (et je n'ai pas eu le courage d'attendre jusqu'à la fin... En fait il y a une major collection (Full GC) à chaque itération... et chaque "Full GC" prend environ 40ms... Si on calcule bien au final cela représente plus de 30 minutes !!!
Tout cela pour libérer un seul objet ! Le problème est que les "Full GC" sont bien plus couteux, et qu'ils sont appelés inutilement...
Bref :
System.gc() est vraiment à utiliser dans des cas très rare, et surtout pas dans une boucle !!!
Quand à la différence entre le serveur de dev et de prod, cela vient surement du fait que le
System.gc() n'est pas forcément exécuté. Ce n'est qu'une suggestion et la JVM peut l'ignoré (Utilise
-verboce:gc pour vérifier cela -- attention car ceci peut être couteux car cela génère de gros logs).
a++
Partager