Duffymo a presque certainement raison. Dans le passé, lorsque nous avions des fuites de mémoire, c'était pratiquement TOUJOURS le pilote MySQL JDBC. Oubliant juste de fermer un petit ResultSet ou Connection ou Statement quelque part. J'ai fini par auditer l'intégralité de la base de code à chaque fois que nous les utilisions pour trouver le problème et nous assurer qu'ils étaient résolus.
Quant au HashMap, je l'ai vu aussi. Je n'ai pas regardé la source mais j'ai l'impression que le pilote MySQL stocke les lignes (au moins les valeurs des lignes) dans HashMaps en interne.
Les fuites de ResultSets sont malheureusement faciles. L'idée de ces ressources refermables qui s'en chargent elles-mêmes dans JDK 7 ou 8 m'attire vraiment pour cette raison.
Vous pouvez insérer une classe shim quelque part (par exemple pour Connection) pour enregistrer chaque ressource ouverte/fermée pour voir si vous pouvez détecter où se trouve la fuite sans lire directement toute votre source.