IT • archiv

rus / eng | Логин | Комментарий к статье | Печать | Почта | Клуб




Документация


Управление памятью в Java

 
Java Q&A

Какие типы утечки памяти возможны в Java и как я могу их предотвратить?

В любом языке проблемы управления памятью на уровне приложения возникают вокруг высвобождения памяти. Эти проблемы подразделяются на две категории: преждевременное высвобождение (поврежденные указатели) и неполное высвобождение (утечки памяти).

В случае неполного высвобождения также существуют два подкласса: ошибки кодирования и ошибки дизайна. Ошибки кодирования зависят от языка. В случае C, это связано с вызовом меньшего количества free(), чем malloc(), тогда как в C++ это может включать вызов delete вместо delete[]. Ошибки дизайна, с другой стороны, не зависят от языка; вместо этого, они связаны с простой небрежностью программиста.

В языках вроде C/C++, все управление памятью зависит от программиста, так что могут возникать все виды проблем, даже после того, как программист затратил массу усилий чтобы удостовериться, что код свободен от подобных деффектов. На самом деле, в C/C++ чем больше вы пытаетесь избежать утечек памяти, тем больше вы создаете поврежденных указателей и наоборот. И, поскольку естественный риск возникновения таких ошибок увеличивается с усложнением и увеличением кода, очень трудно защитить большие приложения на C/C++ от этого типа ошибок.

В Java, с другой стороны, язык Java и исполняющий код вместе устраняют проблему поврежденных указателей и утечек памяти на уровне кода. Вот как это работает:

  • В Java память выделяется только для объектов. Здесь не существует произвольного выделения памяти, только создание новых объектов (Java даже обрабатывает массивы, как объекты).
  • Исполняющий код в Java (runtime) использует сборщик мусора для высвобождения памяти, занимаемой объектом, как только он определяет, что объект более недоступен. Этот автоматический процесс делает безопасным освобождение ненужных ссылок на объекты, так как сборщик не будет уничтожать объект, который еще где-либо используется. Следовательно, в Java, процесс уничтожения ненужных ссылок никогда не приводит к риску преждевременного высвобождения памяти.
  • В Java можно легко уничтожить целое "дерево" объектов, установив ссылку в корне дерева в null; сборщик мусора, затем, уничтожит все объекты (если, конечно, некоторые из них не используются где-то еще). Это гораздо проще, чем кодирование деструктора для каждого объекта, чтобы можно было высвободить все зависимые ресурсы (это большая проблема при написании кода на C++).

Так как насчет утечек памяти связанных с плохим дизайном? В случае подобных дизайнов, ненужные ссылки на объекты, созданные на нижнем уровне системы не дают сборщику мусора высвобождать неиспользующиеся объекты. Такие ошибки обычно включают "большие" проблемы, когда неправильно включаются ссылки на объекты в разных частях кода.

Другие недостатки дизайна можно считать "маленькими" проблемами, на уровне ошибочного алгоритма; использование объектов вроде Collections в таких случаях умножает ошибки.

С улучшением технологии, хорошо реализованные виртуальные машины (JVM) могут помочь уменьшить эффекты таких вызванных дизайном утечек памяти, используя сборщик мусора, который отслеживает использование объекта во времени. Такой сборщик мусора может перераспределить объекты в памяти в соответствии с фактором "свежести", основанном на времени последней ссылки на них, например. Старые объекты будут вытесняться в своп (хотя, для безопасности, не будут полностью удалены).

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

Заключение: Проблемы дизайна могут быть уменьшены путем удаления ссылки на объект как можно скорее (зная, что в Java не существует риск повреждения другого участка кода).

Совет: Инструмент JProbe от KL Group может помочь обнаружить возможные источники утечек памяти, показывая граф владельцев ссылок на объекты.

Заметьте: Реализации JVM от Sun до HotSpot использовали технику, известную как conservative garbage collection, которая может вносить утечки памяти сама по-себе, помимо вызванных программистом. Кратко, если приложение содержит 32-битный примитив integer (int), чье значение совпадает с адресом объекта, сборщик мусора не сможет высвободить такой объект. Несмотря на то, что вероятность такого события мала, она не равна нулю. Из-за этого, и для лучшей общей производительности, старайтесь использовать HotSpot.

Об авторе

Random Walk Computing это наибольшая консалтинговая фирма в Нью Йорке, специализирующаяся на Java/CORBA решениях для предприятий. Известные своим выдающимся знанием Java, консультанты Random Walk публикуются и выступают на самых престижных форумах мира. Для связи с Random Walk используйте javaqa@javaworld.com.

Ресурсы

Related reading in JavaWorld

Reprinted with permission from the August 1999 edition of JavaWorld magazine. Copyright © ITworld.com, Inc., an IDG Communications company.
View the original article at: http://www.javaworld.com/javaworld/ javaqa/1999-08/04-qa-leaks.html



Перевод на русский © Сергей Миссан, 2000

Справка | Условия Copyright © 1999 — 2010, IT • archiv.
В начало | Логин | Комментарий к статье | Поиск | Почта