Можете воспользоваться логом для сборщика мусора.
java -Xloggc:<файл для вывода лога> -XX:+PrintGCDetails -XX:+PrintGCDateStamps <ваша программа с флагами>
На разных JVM флаги и формат вывода разный.
Вот что вы скорее всего увидете.
[GC 245118K->214677K(1571712K) eden 30464K->0K survivor 247K->270K tenured 214406K->214406K, 0.0212236 secs]
[GC 245141K->214708K(1571712K) eden 30463K->0K survivor 270K->301K tenured 214406K->214406K, 0.0229019 secs]
[GC 245172K->214692K(1571712K) eden 30463K->0K survivor 301K->285K tenured 214406K->214406K, 0.0241589 secs]
[GC 245156K->214747K(1571712K) eden 30463K->0K survivor 285K->340K tenured 214406K->214406K, 0.0245928 secs]
Здесь используется сборщик мусора с тремя кучами (три поколения) eden, survivor и tenured.
У каждого из них есть характеристики сколько бы до сборки и сколько осталось после (eden 30463K->0K).
В начале есть общая характеристика которая вас наверное и интересует. В ней также указан объем памяти занимаемый объектами до сборки и после сборки, а также в скобках указан общий объём кучи. Кроме этих поколений есть также и permanent generation, где хранится информация о классах и статические поля. Во многих моментах я могу ошибаться, но надеюсь я помог с направлением поиска.
Ещё есть
GCViewer - визуализирует состояние сборщика и собирает общую статистику.
Если вы найдёте какую-нибудь документацию по формату лога сборщика - поделитесь ссылкой. Был бы благодарен.