Свободная память от сложных объектов в Java

Я стараюсь изо всех сил объяснить свой вопрос. Может быть, это немного абстрактно.

Я прочитал некоторую литературу о том, что я не объясняю GC явно в Java-коде, метод finalize, указывающий на null и т.д.

У меня есть несколько больших файлов XMLs (клиентские счета). Использование Jaxb, файловые маршалы в сложном Java-объекте. Его атрибуты - это базовые типы (Integer, BigDecimal, String и т.д.), Но также класс других сложных классов, список других классов, список классов со списком как атрибут и т.д.

Когда я делаю свой материал с объектом, мне нужно удалить его из памяти. Некоторые XML очень большие, и я могу избежать утечки памяти или ситуации OutOfMemoryError.

Итак, мои вопросы:

  • Достаточно ли присвоить большой объект null? Я читал, что если есть мягкие ссылки, GC не освободит объект.
  • Должен ли я выполнить глубокую очистку объекта, очистить весь список, присвоить значение null атрибутам и т.д.?
  • Как насчет JaxB (я использую Java6, поэтому JaxB построен) и мягкие ссылки? JaxB работает быстрее, чем старый маршаллер JibX, но я не знаю, хуже ли это в использовании памяти.
  • Должен ли я обернуть класс jaxB megacomplex с помощью WeakReference или что-то вроде этого?

Извините меня за смешение концепций использования памяти Java, JaxB и т.д. Я изучаю стабильность большого работающего процесса, а файлы .hprof свидетельствуют о том, что все данные клиентов всех счетов-фактур остаются в памяти. Извините, если это простой, простой или редкий вопрос.

Заранее спасибо

Ответ 1

Если что-то еще не указывает на части вашего большого объекта (графика), достаточно назначить ссылку на большой объект null.

Безопаснее всего было бы использовать профилировщик после того, как ваше приложение какое-то время работало, и посмотрите на ссылки на объекты и посмотрите, есть ли что-то, что не соответствует GC.

Ответ 2

Достаточно ли присвоить большой объект null? Я читал, что если есть мягкие ссылки, GC не освободит объект.

Короткий ответ да. Достаточно назначить (все сильные ссылки) большому объекту на нуль - если вы сделаете это, объект больше не будет считаться "сильно достижимым" сборщиком мусора.

Мягкие ссылки не будут проблемой в вашем случае, потому что это гарантирует, что объекты с мягким достижением будут собирать мусор до того, как будет выброшен OutOfMemoryError. Они могут помешать сборщику мусора немедленно собрать объект (если они этого не сделали, они будут действовать точно так же, как слабые ссылки). Но использование этой памяти было бы "временным", поскольку оно было бы освобождено, если бы это было необходимо для выполнения запроса на распределение.

Должен ли я выполнить глубокую очистку объекта, очистить весь список, присвоить значение null атрибутам и т.д.?

Возможно, это будет плохая идея. Если значения поля ссылаются только на внешний большой объект, тогда они также будут собираться мусором, когда собирается большой объект. И если это не так, то другие части кода, которые ссылаются на них, не будут рады видеть, что вы удаляете членов из списка, который они используют!

В лучшем случае это ничего не делает, и в худшем случае это нарушит вашу программу. Не позволяйте соблазну этого отвлекать вас от решения единственного вопроса о том, является ли ваш объект сильно доступным или нет.

Как насчет JaxB (я использую Java6, поэтому JaxB встроен) и мягкие ссылки? JaxB быстрее, чем старый маршаллер JibX, но я не знаю, хуже ли это в использовании памяти.

Я не особенно знаком с относительной производительностью времени и пространства этих библиотек. Но в целом, это безопасно, чтобы принять очень сильное "невиновное, пока не доказано, виноватое" отношение с основными библиотеками. Если бы была ошибка утечки памяти, она, вероятно, была бы найдена, зарегистрирована и исправлена ​​к настоящему времени (если вы не делаете что-то очень нишу).

Если есть утечка памяти, я на 99,9% уверен, что это ваш собственный код, который по ошибке.

Должен ли я обернуть класс jaxB megacomplex с помощью WeakReference или что-то вроде этого?

Это звучит так, будто вы можете бросить GC "исправления" в проблему, не задумываясь о том, что на самом деле необходимо.

Если класс JaxB следует слабо ссылать, то, во всяком случае, это хорошая идея (и она должна быть там уже). Но если это не так, то определенно не делайте этого. Слабые ссылки - это скорее вопрос общей семантики, а не то, что вы вводите специально, чтобы избежать проблем с памятью.

Если внешнему коду нужна ссылка на объект, тогда ему нужна ссылка - нет волшебства, которое вы можете сделать, чтобы иметь возможность собирать мусор, но все еще доступен. Если ему не нужна ссылка (за какой-то определенной точкой), тогда она не нужна вообще - лучше просто аннулировать стандартную [сильную] ссылку или позволить ей выпасть из области видимости. Слабые ссылки - это особая ситуация и обычно используются, когда у вас нет полного контроля над точкой, в которой объект перестает быть релевантным. Скорее всего, это не так.

.hprof файлы свидетельствуют о том, что все данные клиентов всех счетов-фактур остаются в памяти.

Это говорит о том, что на них действительно ссылаются дольше, чем это необходимо.

Хорошей новостью является то, что файл hprof будет содержать сведения о том, что именно ссылается на них. Посмотрите на экземпляр счета-фактуры, который вы ожидали бы от GCed, и посмотрите, что ссылается на него и не позволяет ему быть GCed. Затем загляните в класс, о котором идет речь, чтобы узнать, как вы ожидаете, что ссылка будет освобождена, и почему она не была в этом случае.

Все хорошие настройки производительности/памяти основаны на измерениях. Принимая кучи кучи, проверяя экземпляры и ссылки на них, ваши измерения. Сделайте это и действуйте по результатам, а не пытайтесь обернуть вещи в WeakReferences, надеясь, что это может помочь.

Ответ 3

Вы написали

hprof files evidence that all customers data of all invoices remains in memory. 

Вы должны проанализировать его, используя mat. Некоторые хорошие заметки в http://memoryanalyzer.blogspot.in/