Es casi seguro que Duffymo tiene razón. En el pasado, cuando hemos tenido fugas de memoria, es prácticamente SIEMPRE el controlador MySQL JDBC. Simplemente olvidé cerrar un pequeño ResultSet o Connection o Statement en alguna parte. Terminé auditando todo el código base cada vez que los usamos para encontrar el problema y asegurarnos de que se cerraran.
En cuanto al HashMap, también lo he visto. No miré la fuente, pero mi impresión fue que el controlador MySQL almacenó las filas (al menos los valores de fila) en HashMaps internamente.
La fuga de ResultSets es lamentablemente fácil. La idea de esos recursos que se pueden cerrar que se encargan de esto por sí mismos en JDK 7 u 8 realmente me atrae por este motivo.
Podría insertar una clase de corrección en algún lugar (digamos para Conexión) para registrar cada recurso abierto/cerrado para ver si puede detectar dónde está la fuga sin leer directamente toda su fuente.