У меня есть проблема с некоторой платформой API, называя BufferedImage.getGraphics () методом и таким образом вызывая утечку памяти. То, что делает этот метод, - то, что он всегда называет BufferedImage.createGraphics (). На машине окон, createGraphics () обрабатывается Win32GraphicsEnvironment, который сохраняет список слушателей в его поле displayChanger. То, когда я называю getGraphics на своем BufferedImage someChart, SurfaceManager someChart (который сохраняет ссылку на someChart), добавляется к карте слушателей в Win32GraphicsEnvironment, предотвращая someChart, чтобы быть собранным "мусор". Ничто впоследствии не удаляет SurfaceManager someChart из карты слушателей.
В целом итоговый путь, мешающий BufferedImage быть собранным "мусор", однажды getGraphics, называют, следующие:
Корень GC-> localGraphicsEnvironment (Win32GraphicsEnvironment)-> displayChanger (SunDisplayChanger)-> слушатели (Карта)-> ключ (D3DChachingSurfaceManager)-> bImg (BufferedImage)
Я, возможно, изменил код платформы так, чтобы после каждого названного к BufferedImage.getGraphics (), я сохранил ссылку на SurfaceManager BufferedImage. Затем я овладеваю localGraphicsEnvironment, бросаю его к Win32GraphicsEnvironment, затем называю removeDisplayChangedListener () использованием ссылки на SurfaceManager BufferedImage. Но я не думаю, что это - надлежащий способ решить проблему.
Кто-то мог помочь мне с этой проблемой?Большое спасибо!
БОЛЬШЕ ДЕТАЛЕЙ И РЕЗУЛЬТАТОВ
Компонент, который я пытаюсь добавить к своему UI, выполняет вызовы к BufferedImage.getGraphics () каждый раз, когда он перекрашен. В результате количество мусора, сохраненного displayChanger (в SunGraphicsEnvironment), должно вырасти, поскольку компонент перекрашен.
Однако вещи поведение достаточно странно:
когда я считал свои действия с моим UI, который, конечно, инициирует перекрашивание, затем проверить число слушателей мусора внутри displayChanger против моего количества, они не совпадают. (например, перед моими щелчками было 8 слушателей, и я сделал 60 щелчков. В конце концов, существует только 18 слушателей.)
С другой стороны, если я включаю точку останова и шаг в процесс добавляющих вещей к displayListeners, каждый щелчок привел к новой записи в displayListeners. И таким образом, каждый BufferedImage, сохраненный displayListeners, становится мусором.
Я рассмотрел возможность SurfaceManager, который используется в качестве ключа для displayListeners, может быть совместно использован или снова использован, все же мой эксперимент исключил эту возможность. Я также рассмотрел кэширование, и я сознательно предотвратил кэширование путем совершения каждого вызова для перекрашивания уникальный. Однако, у меня нет подсказки, как это могло произойти и как решить утечку.
После рендеринга BufferedImage
вы должны вызвать dispose ()
в графическом контексте, возвращаемом createGraphics ()
. Вот пример и список похожих методов.
Приложение: Это похоже на утечку объекта под названием packratting ; несоответствие слушателя звучит как артефакт использования отладчика. Некоторые идеи можно почерпнуть из статьи Брайана Гетца Устранение утечек памяти с помощью мягких ссылок .
Попробуйте вызвать flush ()
, когда вам больше не нужно изображение.