Hallo,
es gibt je nach verwendetem GC-Algo einen oder mehreren GC Threads
(Parallel GC, Beispielsweise Concurrent Mark and Sweep (CMS)).
Wird System.gc() aus Anwendungscode aus aufgerufen, so wird
intern ein GC Request eingestellt. Die JVM bekommt also einen
Hinweis bei der nächsten möglichen Gelegenheit einen GC zu machen.
Dieser GC lauft dann in einem der GC Threads ab. Nicht auf in dem
Thread, der System.gc() aufgerufen hat.
Weiterhin bleiben bei einem Stop-the-World GC Vorgang "alle" Threads
(außer die für den GC) stehen. Nicht nur einer ;-).
Um festzustellen, welche Objekte der GC aus dem Speicher entfernen kann, schaut
er nach welche Objekte noch von einem Thread aus direkt (oder auch indirekt)
referenziert werden können. Je nach GC Algo werden nun die nicht mehr erreichbaren
Objekte direkt weggeräumt, oder markiert und anschließend beim nächsten Durchlauf
freigegeben.
Je nach verwendeten GC Algo muss zum Analysieren des Systemzustandes ein Snapshot erstellt werden.
Das ist natürlich viel einfacher wenn alle Threads gestoppt werden (stop-the-world).
Es gibt aber auch (sehr komplizierte) GC Algorithmen welche die Stop the World Zeiten
sehr klein halten oder gar ganz eliminieren können.
Die Frage ob ein explizites System.gc() bei Mehrprozessor- / Mehrkernsystem
zu Problemen führt kann ich mit jein beantworten, wobei mir bezüglich korruptem
Speicher noch nichts untergekommen ist.
Ein explizites System.gc() kann unter umständen die Performance der Anwendung
erheblich verschlechten. Heute GCs arbeiten in der Regel sehr zuverlässig und sind
selbst adaptiv. D.h. sie steuern ihren Einsatz selbst. Was hochperformante GC Operationen
ermöglict. Greift der Anwender nun mit einer Folge von manuellen System.gc() aufrufen
dazwischen so bringt er dieses selbstorganisierende System aus dem tritt und schon wird
u.U. ein Full-GC gemacht, welcher 1) absolut unnötig ist und 2) das System ausbremst.
Gruß Tom