è una caratteristica nota del garbage collector di java
dunque: il meccanismo è relativamente semplice...
la vm alloca memoria a gogo, mettendo classi qua e là..
dato che in java non esistono puntatori visibili, tenere sotto controllo i riferimenti ad un dato ogetto è relativamente poco dispendioso.. dal momento in cui si tratta solo di passare al setaccio tutti i nomi di variabile dichiarati e tutti gli oggetti allocati, vedere quali non hanno un riferimento, ed eliminare quindi l'oggetto liberando spazio.
Ora, visto così questo meccanismo sembra funzionante in ogni momento ma non è così, e ti spiego perchè.
Questo processo, essendo un processo alquanto bastardo in termini di riduzione delle prestazioni del sistema, è stato ridotto ad essere chiamato solo in momenti di fabbisogno di memoria, ovvero, quando si sfonda il tetto della memoria fisica disponibile, o si tira giù l'intera VM. quindi, capita spessissimo, che durante tutto l'arco di vita dell'applicazione in realtà il GC non butti via niente, semplicemente perchè non ce n'è bisogno.
Attraverso l'utilizzo di System.gc(), noi possiamo però forzare l'esecuzione del garbage collector, ma è probabile che nel tuo caso nemmeno funzioni, perchè in realtà il garbage collector non si limita a fare solo controllo e deallocazione, ma bensì ha un meccanismo un pò più complesso rispetto a come ti ho accennato sopra in "grandi linee".. per renderti l'idea considera che parte ogni tot tempo, ed effettua però solo la "marcatura" delle allocazioni che è possibile eliminare senza problemi.. marcature che poi distrugge realmente solo in caso di necessità di memoria.
per ulteriori delucidazioni puoi provare a leggere qui, nella parte del garbage collector.
http://www.mokabyte.it/1996/11/java_c++.htm