Есть ли способ освободить память в Java, похожий на free()
функцию C ? Или установка объекта в null и использование GC - единственный вариант?
Есть ли способ освободить память в Java, похожий на free()
функцию C ? Или установка объекта в null и использование GC - единственный вариант?
Ответы:
Java использует управляемую память, поэтому единственный способ распределить память - использовать new
оператор, а единственный способ освободить память - использовать сборщик мусора.
Этот технический документ по управлению памятью (PDF) может помочь объяснить, что происходит.
Вы также можете позвонить System.gc()
и предложить немедленно запустить сборщик мусора. Тем не менее, среда выполнения Java принимает окончательное решение, а не ваш код.
Согласно документации Java ,
Вызов метода gc предполагает, что виртуальная машина Java затрачивает усилия на утилизацию неиспользуемых объектов, чтобы сделать доступной память, которую они занимают, для быстрого повторного использования. Когда управление возвращается из вызова метода, виртуальная машина Java сделала все возможное, чтобы освободить пространство от всех отброшенных объектов.
System.gc()
полностью игнорируют .
Кажется, никто не упомянул явную установку ссылок на объекты null
, что является законным методом «освобождения» памяти, которую вы, возможно, захотите рассмотреть.
Например, допустим, что List<String>
в начале метода вы объявили метод, размер которого увеличился до очень большого, но требовался только до середины метода. В этот момент вы можете установить ссылку List, чтобы null
сборщик мусора мог потенциально вернуть этот объект до завершения метода (и ссылка в любом случае выпадает из области видимости).
Обратите внимание, что я редко использую эту технику в реальности, но это стоит учитывать при работе с очень большими структурами данных.
System.gc();
Запускает сборщик мусора.
Вызов метода gc предполагает, что виртуальная машина Java затрачивает усилия на утилизацию неиспользуемых объектов, чтобы сделать доступной память, которую они занимают, для быстрого повторного использования. Когда управление возвращается из вызова метода, виртуальная машина Java сделала все возможное, чтобы освободить пространство от всех отброшенных объектов.
Не рекомендуется.
Редактировать: я написал оригинальный ответ в 2009 году. Сейчас 2015.
Сборщики мусора неуклонно улучшались за последние 20 лет существования Java. На этом этапе, если вы вручную вызываете сборщик мусора, вы можете рассмотреть другие подходы:
* «Я лично полагаюсь на обнуление переменных в качестве заполнителя для будущего правильного удаления. Например, я беру время, чтобы аннулировать все элементы массива, прежде чем фактически удалить (сделать ноль) сам массив».
Это не нужно. Способ работы Java GC заключается в том, что он находит объекты, которые не имеют на них ссылки, поэтому, если у меня есть Object x со ссылкой (= variable) a, которая указывает на него, GC не удалит его, потому что есть ссылка к этому объекту:
a -> x
Если вы ноль, чем это происходит:
a -> null
x
Так что теперь x не имеет ссылки, указывающей на него, и будет удалено. То же самое происходит, когда вы устанавливаете ссылку на объект, отличный от x.
Поэтому, если у вас есть массив arr, который ссылается на объекты x, y и z, и переменная a, которая ссылается на массив, это выглядит так:
a -> arr -> x
-> y
-> z
Если вы ноль, чем это происходит:
a -> null
arr -> x
-> y
-> z
Таким образом, GC находит arr как не имеющий ссылки на него и удаляет его, что дает вам такую структуру:
a -> null
x
y
z
Теперь GC находит x, y и z и удаляет их тоже. Обнуление каждой ссылки в массиве не сделает ничего лучше, оно просто израсходует процессорное время и пространство в коде (тем не менее, это не повредит дальше. GC все равно сможет работать так, как должен) ).
Причиной желания освободить память из любой программы (Java или нет) является выделение большего объема памяти другим программам на уровне операционной системы. Если мое java-приложение использует 250 МБ, я могу уменьшить его до 1 МБ и сделать 249 МБ доступными для других приложений.
Чтобы расширить ответ и комментарий Яниса Ксантофулоса и Hot Licks (извините, я пока не могу комментировать!), Вы можете установить параметры виртуальной машины, как в этом примере:
-XX:+UseG1GC -XX:MinHeapFreeRatio=15 -XX:MaxHeapFreeRatio=30
В моем jdk 7 это освободит неиспользуемую память виртуальной машины, если более 30% кучи освободится после GC, когда виртуальная машина простаивает. Вам, вероятно, нужно будет настроить эти параметры.
Хотя я не видел, чтобы это подчеркивалось в приведенной ниже ссылке, обратите внимание, что некоторые сборщики мусора могут не подчиняться этим параметрам, и по умолчанию java может выбрать один из них для вас, если у вас есть более одного ядра (отсюда и аргумент UseG1GC выше ).
Обновление: для java 1.8.0_73 я видел, как JVM иногда выпускает небольшие суммы с настройками по умолчанию. По-видимому, делает это только в том случае, если ~ 70% кучи не используется, хотя ... не знаю, будет ли более агрессивное освобождение, если в ОС недостаточно физической памяти.
Я провел эксперименты на этом.
Это правда, что System.gc();
предлагает только запустить сборщик мусора.
Но вызов System.gc();
после установки всех ссылок на null
, улучшит производительность и занятость памяти.
Если вы действительно хотите выделить и освободить блок памяти, вы можете сделать это с помощью прямых байтовых буферов. Существует даже непереносимый способ освобождения памяти.
Однако, как уже было предложено, то, что вам нужно освободить память в C, вовсе не означает, что это хорошая идея.
Если вы считаете, что у вас действительно хороший вариант использования free (), пожалуйста, включите его в вопрос, чтобы мы могли видеть, что вы хотите сделать, вполне вероятно, что есть лучший способ.
Полностью от javacoffeebreak.com/faq/faq0012.html
Поток с низким приоритетом автоматически заботится о сборке мусора для пользователя. Во время простоя поток может быть вызван, и он может начать освобождать память, ранее выделенную объекту в Java. Но не волнуйтесь - это не удалит ваши объекты на вас!
Когда нет ссылок на объект, он становится честной игрой для сборщика мусора. Вместо вызова некоторой подпрограммы (например, free в 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 ++), я, по крайней мере, хочу отдать должное освобождению памяти должным образом, чтобы в дальнейшем это помогло процессу портирования.
Я лично полагаюсь на обнуление переменных в качестве заполнителя для будущего правильного удаления. Например, я беру время, чтобы аннулировать все элементы массива, прежде чем фактически удалить (сделать ноль) сам массив.
Но мой случай очень специфичен, и я знаю, что при этом бьюсь об эффективности.
* "Например, допустим, вы объявили List в начале метода, размер которого увеличился до очень большого, но требовался только до середины метода. В этот момент вы можете установить для ссылки List значение null позволить сборщику мусора потенциально восстановить этот объект до завершения метода (и ссылка в любом случае выходит из области видимости). " *
Это правильно, но это решение не может быть обобщено. При установке ссылки на объект List на null -will- сделать память доступной для сборки мусора, это верно только для объекта List примитивных типов. Если вместо этого объект List содержит ссылочные типы, установка объекта List = null не разыменует -any- ссылочных типов, содержащихся в списке. В этом случае установка параметра List object = null приведет к потере всех содержащихся ссылочных типов, чьи объекты не будут доступны для сборки мусора, если алгоритм сбора мусора не достаточно умен, чтобы определить, что объекты были осиротевшими.
По всей Java обеспечивает автоматическую сборку мусора, иногда вам нужно знать, насколько велик объект и сколько его осталось. Свободно использовать память программно import java.lang;
и Runtime r=Runtime.getRuntime();
получать значения памяти, используя mem1=r.freeMemory();
для освобождения памяти вызов r.gc();
метода и вызоваfreeMemory()
Рекомендация от JAVA - присвоить нуль
С https://docs.oracle.com/cd/E19159-01/819-3681/abebi/index.html
Явное присвоение нулевого значения переменным, которые больше не нужны, помогает сборщику мусора идентифицировать части памяти, которые можно безопасно восстановить. Хотя Java обеспечивает управление памятью, она не предотвращает утечки памяти и не использует чрезмерное количество памяти.
Приложение может вызывать утечки памяти, не освобождая ссылки на объекты. Это не позволяет сборщику мусора Java вернуть эти объекты и приводит к увеличению объема используемой памяти. Явное аннулирование ссылок на переменные после их использования позволяет сборщику мусора освобождать память.
Одним из способов обнаружения утечек памяти является использование инструментов профилирования и создание снимков памяти после каждой транзакции. Приложение без утечек в устойчивом состоянии будет показывать устойчивую активную память кучи после сборок мусора.