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

Есть ли способ освободить память на Java, аналогичную функции C free()? Или задает объект null и полагается только на GC?

Ответ 1

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

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

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

Согласно документации Java,

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

Ответ 2

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

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

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

Ответ 3

System.gc(); 

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

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

Не рекомендуется.

Изменить: я написал исходный ответ в 2009 году. Сейчас 2015 год.

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

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

Ответ 4

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

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

a -> x

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

a -> null
     x

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

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

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

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

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

Таким образом, GC обнаруживает, что arr не имеет ссылки на него и удаляет его, что дает вам эту структуру:

a -> null
     x
     y
     z

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

Ответ 5

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

Ответ 6

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

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

Но вызов System.gc(); после установки всех ссылок на нуль,

улучшит производительность и занятость памяти.

Ответ 7

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

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

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

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

Аргументы виртуальной машины

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

Ответ 8

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

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

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

Ответ 9

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

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

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

Пример:

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();

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

Ответ 10

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

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

Но мой случай очень специфичен, и я знаю, что при этом делаю ударные качества.

Ответ 11

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

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

Ответ 12

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