Как освободить память в Java?

есть ли способ освободить память в Java, аналогично c ? Или установка объекта в null и полагаться на GC-единственный вариант?

13 ответов


Java использует управляемую память, поэтому единственный способ выделить память-использовать new оператор, и единственный способ освободить память-полагаться на сборщик мусора.

этой управление памятью whitepaper (PDF) может помочь объяснить, что происходит.

вы также можете позвонить System.gc() чтобы предложить немедленно запустить сборщик мусора. Однако окончательное решение принимает среда выполнения Java, а не ваш код.

по данным the Java документация,

вызов метода gc предполагает, что виртуальная машина Java израсходовала усилие к утилизации неиспользуемых объектов в чтобы сделать память, они в настоящее время занимать быстрые повторное использование. Когда управление возвращается из вызова метода, виртуальная машина Java приложил все усилия, чтобы вернуть пространство от всех отброшенных объектов.


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

например, скажем, вы объявили List<String> в начале метода, который вырос в размере, чтобы быть очень большим, но требовался только до половины пути через метод. На этом этапе вы можете установить ссылку на список в null чтобы разрешить сборщику мусора потенциально освободить этот объект перед методом завершает (и ссылка все равно выпадает из области действия).

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


System.gc(); 

запускает сборщик мусора.

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

не рекомендуемый.

Edit: я написал оригинальный ответ в 2009 году. Сейчас 2015.

сборщики мусора неуклонно улучшались в течение ~20 лет Java. На этом этапе, если вы вручную вызываете сборщик мусора, вы можете рассмотреть другие подходы:

  • если вы заставляете GC на ограниченном количестве машин, возможно, стоит иметь точку балансировки нагрузки до из текущего машина, ожидая, пока она закончит обслуживать подключенных клиентов, тайм-аут после некоторого периода для зависания соединений,а затем просто перезагрузите JVM. Это ужасное решение, но если вы смотрите на систему.gc (), принудительные перезагрузки могут быть возможной временной задержкой.
  • рассмотрите возможность использования другого сборщика мусора. Например, (Новый за последние шесть лет) коллектор G1-это модель с низкой паузой; он использует больше ЦП в целом, но лучше никогда не заставлять жесткую остановку при выполнении. Поскольку серверные процессоры теперь почти все имеют несколько ядер,это действительно хороший компромисс.
  • посмотрите на использование памяти настройки флагов. Особенно в новых версиях Java, если у вас не так много долгосрочных запущенных объектов, рассмотрите возможность увеличения размера newgen в куче. newgen (young) - это место, где выделяются новые объекты. Для веб-сервера все, созданное для запроса, помещается здесь, и если это пространство слишком мало, Java потратит дополнительное время на обновление объекты для более долгоживущей памяти, где их дороже убить. (Если newgen немного слишком мал, вы заплатите за это.) Например, в G1:
    • XX: G1NewSizePercent (по умолчанию 5; вероятно, не имеет значения.)
    • XX:G1MaxNewSizePercent(по умолчанию 60; вероятно, поднимите это.)
  • расскажете сборщик мусора ты не в порядке с длинную паузу. Это приведет к более частым запускам GC, что позволит системе сохранить остальное-ограничения. В G1:
    • XX: MaxGCPauseMillis (по умолчанию 200.)

* " я лично полагаюсь на переменные nulling в качестве заполнителя для будущего правильного удаления. Например, я использую время, чтобы аннулировать все элементы массива, прежде чем фактически удалить (сделать null) сам массив."

Это лишнее. Способ работы Java GC заключается в том, что он находит объекты, которые не имеют ссылки на них, поэтому, если у меня есть объект x со ссылкой (=переменная) a, которая указывает на него, GC не удалит его, потому что есть ссылка на это объект:

a -> x

если вы null a, чем это происходит:

a -> null
     x

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

поэтому, если у вас есть arr массива, который ссылается на объекты x, y и z и переменную a, которая ссылается на массив, это выглядит так:

a -> arr -> x
         -> y
         -> z

если вы null a, чем это происходит:

a -> null
     arr -> x
         -> y
         -> z

Итак, GC находит arr как не имеющий ссылки на него и удаляет его, что дает вам эту структуру:

a -> null
     x
     y
     z

теперь GC находит x, y и z и удаляет их также. Обнуление каждой ссылки в массиве не сделает ничего лучше, он просто будет использовать время и пространство процессора в коде (тем не менее, это не повредит дальше. GC по-прежнему сможет выполнять то, что он должен).


действительная причина для желания освободить память от любой программы (java или нет) - сделать больше памяти доступной для других программ на уровне операционной системы. Если мое приложение java использует 250 МБ, я могу заставить его уменьшить до 1 МБ и сделать 249 МБ доступным для других приложений.


Я провел эксперименты над этим.

Это правда System.gc(); только предлагает запустить сборщик мусора.

но вызов System.gc(); после установки всех ссылок на null, улучшит представление и занятие памяти.


чтобы продлить ответ и комментарий от Yiannis Xanthopoulos and Hot Licks (извините, я пока не могу комментировать!), вы можете установить параметры VM, как в этом примере:

-XX:+UseG1GC -XX:MinHeapFreeRatio=15 -XX:MaxHeapFreeRatio=30

в моем jdk 7 это освободит неиспользуемую память виртуальной машины, если более 30% кучи станет свободным после GC, когда виртуальная машина простаивает. Вероятно, вам нужно будет настроить эти параметры.

хотя я не видел, чтобы это подчеркивалось в ссылке ниже, обратите внимание, что некоторые сборщики мусора могут не подчиняться этим параметрам и по умолчанию java может выбрать один из них для вас, если у вас есть более одного ядра (следовательно, аргумент UseG1GC выше).

параметры VM

Update: для java 1.8.0_73 я видел, что JVM иногда выпускает небольшие суммы с настройками по умолчанию. Кажется, только сделать это, если ~70% кучи не используется.. не знаю, было бы более агрессивным выпуском, если бы у ОС была низкая физическая память.


Если вы действительно хотите выделить и освободить блок памяти, вы можете сделать это с помощью direct ByteBuffers. Существует даже непереносимый способ освободить память.

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

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


полностью из javacoffeebreak.com/faq/faq0012.html

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

когда нет ссылок на объект, он становится честной игрой для сборщик мусора. Вместо того чтобы вызов какой-то рутины (например, free in C++), вы просто назначаете все ссылки на объект null, или назначьте новый класс ссылке.

пример :

public static void main(String args[])
{
  // Instantiate a large memory using class
  MyLargeMemoryUsingClass myClass = new MyLargeMemoryUsingClass(8192);

  // Do some work
  for ( .............. )
  {
      // Do some processing on myClass
  }

  // Clear reference to myClass
  myClass = null;

  // Continue processing, safe in the knowledge
  // that the garbage collector will reclaim myClass
}

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

System.gc();

в сборщик мусора попытается вернуть свободное пространство, а ваш приложение может продолжать выполнение, с таким же объемом памяти, как возможно (проблемы фрагментации памяти могут применяться на определенных платформах).


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

Я лично полагаюсь на переменные nulling в качестве заполнителя для будущего правильного удаления. Например, я использую время, чтобы аннулировать все элементы массива, прежде чем фактически удалить (сделать null) сам массив.

но мой случай очень особенный, и я знаете, я беру производительности при этом.


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

Это правильно, но это решение может не быть обобщенным. При установке объекта List ссылка на null - сделает память доступной для сборки мусора, это верно только для объекта списка примитивных типов. Если объект List вместо этого содержит ссылочные типы, установка объекта List = null не разыменует - любой-из ссылочных типов, содержащихся в списке. В этом случае установка list object = null приведет к отключению содержащихся ссылочных типов, объекты которых будут недоступны для сборки мусора, если алгоритм сборки мусора не будет достаточно умен, чтобы определить, что объекты были бесхозными.


Althrough java обеспечивает автоматическую сборку мусора иногда вы захотите узнать, насколько велик объект и сколько его осталось .Свободное использование памяти программно import java.lang; и Runtime r=Runtime.getRuntime(); для получения значений из памяти с помощью mem1=r.freeMemory(); чтобы освободить память называют r.gc(); метод и вызов freeMemory()


рекомендация от JAVA-назначить null

от https://docs.oracle.com/cd/E19159-01/819-3681/abebi/index.html

явное присвоение значения null переменным, которые больше не нужны, помогает сборщику мусора идентифицировать части памяти, которые можно безопасно восстановить. Хотя Java обеспечивает управление памятью, это не предотвращает утечки памяти или использование чрезмерного объема памяти.

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

один из способов обнаружения утечек памяти-использовать инструменты профилирования и делать снимки памяти после каждой транзакции. Свободное от утечк применение в устоичивом состоянии покажет устоичивое активное памяти после сборки мусора.