Я унаследовал Java-апплет (фактический <APPLET>), который выдает исключение OutOfMemory примерно через 4 дня работы. Природа апплета такова, что люди действительно оставляют его открытым на долгие периоды времени.
По прошествии почти двух дней работы jmap -histo показывает верхних потребителей кучи как:
num #instances #bytes class name
--- ---------- ------ ----------
1: 14277 7321880 <constantPoolKlass>
2: 59626 5699968 <constMethodKlass>
3: 14047 5479424 <constantPoolCacheKlass>
4: 14277 5229744 <instanceKlassKlass>
5: 59626 4778944 <methodKlass>
6: 71026 3147624 <symbolKlass>
Проблема в том, что я не понимаю, что это такое. Происходит как минимум две вещи: constantPoolKlass + constantPoolCacheKlass + instanceKlassKlass кажутся связанными, как и constMethodKlass + methodKlass. Судя по названиям, они связаны с загрузчиком классов.
Если бы мне пришлось угадывать, я бы сказал, что апплет создал около 14 277 объектов, каждый из которых имеет около 4 методов, всего около 59626 методов. Тем не менее, вывод jmap не показывает ни одного класса с таким большим количеством экземпляров, и не похоже, что общая сумма других объектов класса составляет 14277. Так что, возможно, я ошибаюсь в том, что делают эти объекты. Кто-нибудь может объяснить?




Ага, похоже, у вас утечка загрузчиков классов. Если вы на самом деле не создаете загрузчики классов в своем собственном коде (обычно через URLClassLoader.newInstance или XSLT), это может быть связано с перезагрузкой апплета (хотя вы обычно получаете тот же загрузчик классов). Возможные причины утечек: ThreadLocal, драйверы JDBC и java.beans.
На месте - очевидно, проблема с ClassLoader. Хотя очень странно видеть это в апплете; обычно это проблема только с серверами приложений или IDE.
2 способа отладить это: либо получить настоящий профилировщик кучи, который может показать вам, где указаны данные вашего беглого класса, либо исправить классы API, как описано здесь: http://www.onjava.com/pub/a/onjava/2004/06/30/classloader2.html?page=2