Подтвердить что ты не робот

Понимание управления памятью Java

Java-программисты знают, что JVM запускает сборщик мусора, а System.gc() будет просто предложением JVM для запуска сборщика мусора. Это не обязательно, если мы будем использовать System.gc(), он немедленно запустит GC.

Пожалуйста, исправьте меня, если я неправильно пойму Java Garbage Collector.

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

4b9b3361

Ответ 1

Самое важное, что нужно помнить о управлении памятью Java, - "аннулировать" вашу ссылку.

Только объекты, на которые не ссылаются, должны быть собраны в мусор.

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

List objs = new ArrayList();
for (int i = 0; i  < Integer.MAX_VALUE; i++) objs.add(new Object());

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

List objs = new ArrayList();
for (int i = 0; i  < Integer.MAX_VALUE; i++) new Object();

Итак, что бы вы ни делали, убедитесь, что вы удаляете ссылку на объект, который больше не используется (установите ссылку на null или очистите коллекцию).

Когда сборщик мусора будет работать, лучше всего разрешить JVM. Хорошо, если ваша программа не начнет делать то, что использует много памяти, и имеет критическую скорость, поэтому вы можете предложить JVM запустить GC перед тем, как войти, поскольку вы, вероятно, можете получить собранную мусорную и дополнительную память. Другой разумный, я лично не вижу причин для запуска System.gc().

Надеюсь на эту помощь.

Ответ 2

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

  • Не существует способа ручной сборки мусора в Java.
  • Java Heap делится на три поколения ради сбора мусора. Это молодое поколение, поколение или старое поколение, а также Пермская область.
  • Новые объекты создаются в молодом поколении, а затем переходят в старое поколение.
  • Строковый пул создается в Перми области кучи, сбор мусора может происходить в пермском пространстве, но зависит от JVM к JVM.
  • Малая сборка мусора используется для перемещения объекта из пространства Эдена в пространство Survivor 1 и Survivor 2, а основная коллекция используется для перемещения объекта от молодого поколения к поколению.
  • Всякий раз, когда основная сборка мусора возникает приложением, потоки останавливаются в течение этого периода, что снижает производительность и пропускную способность приложений.
  • В сборке мусора в Java 6 было несколько улучшений производительности, и мы обычно используем JRE 1.6.20 для запуска нашего приложения.
  • Параметры командной строки JVM -Xms и -Xmx используются для установки начального и максимального размера для Java-кучи. Идеальное соотношение этого параметра составляет 1:1 или 1:1,5 на основе моего опыта, например, вы можете использовать оба –Xmx и –Xms как 1 ГБ или -Xms 1,2 ГБ и 1,8 ГБ.

Параметры командной строки: -Xms:<min size> -Xmx:<max size>

Ответ 3

Просто добавьте к обсуждению: Коллекция Garbage не является единственной формой управления памятью в Java.

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

Характеристики RTSJ

  • Бессмертное и ограниченное управление памятью - см. ниже примеры.
  • GC и Immortal/Scoped Memory могут сосуществовать с одним приложением
  • Для RTSJ требуется специально измененная JVM.

Преимущества RTSJ:

  • низкая латентность, отсутствие пауз GC
  • обеспечивает предсказуемую производительность, способную удовлетворить требования к системе реального времени.

Почему RTSJ не удалось/не оказал большого влияния:

  • Концепция ограниченной области памяти сложно программировать, подвергать ошибкам и трудно учиться.
  • В режиме реального времени GC algoritms сократили время паузы GC таким образом, что GC реального времени заменили RTSJ в большинстве приложений реального времени. Тем не менее, Scoped Memories все еще используются в тех местах, где не допускаются задержки.

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

import javax.realtime.*;
public class ScopedMemoryExample{

    private LTMemory myMem;

    public ScopedMemoryExample(int Size) {

       // initialize memory
       myMem = new LTMemory(1000, 5000); 
    }

public void periodicTask() {

  while (true)) {
    myMem.enter(new Runnable() {
        public void run() {
          // do some work in the SCOPED MEMORY
          new Object();
          ...
          // end of the enter() method, the scoped Memory is emptied.  
        }
    });
  }


}
}

Здесь реализована реализация ScopedMemory под названием LTMemory. Затем поток входит в область охваченной памяти, выделяет временные данные, которые необходимы только во время вычисления. По окончании вычисления нить покидает область памяти, которая немедленно освобождает весь контент определенной ScopedMemory. Никакая латентность не вводится, выполняемая в постоянное время, например. предсказуемое время, никакой GC не запускается.

Ответ 4

По моему опыту, в java вы должны полагаться на управление памятью, предоставляемое самой JVM.

В этом разделе я бы сосредоточил внимание на том, чтобы настроить его таким образом, который подходит для вашего варианта использования. Возможно, было бы полезно проверить/понять параметры настройки JVM: http://docs.oracle.com/cd/E15523_01/web.1111/e13814/jvm_tuning.htm

Ответ 5

Вы не можете избежать сбора мусора, если используете Java. Возможно, существуют некоторые неясные реализации JVM, но я ничего не знаю.

Для правильно настроенной JVM не требуется никаких подсказок System.gc() для бесперебойной работы. Точная настройка, в которой вы нуждаетесь, в значительной степени зависит от того, что делает ваше приложение, но, по моему опыту, я всегда включаю параметр параллельной маркировки и развертки со следующим флагом: -XX:+UseConcMarkSweepGC. Этот флаг позволяет JVM использовать дополнительные ядра в вашем процессоре для очистки мертвой памяти на фоновом потоке. Это помогает значительно сократить время, в течение которого ваша программа принудительно приостанавливается при сборе мусора.

Ответ 6

Вы правильно говорите, что System.gc() - это запрос компилятору, а не команда. Но с помощью нижеприведенной программы вы можете убедиться, что это произойдет.

import java.lang.ref.WeakReference;

public class GCRun {

    public static void main(String[] args) {

        String str = new String("TEMP");
        WeakReference<String> wr = new WeakReference<String>(str);
        str = null;
        String temp = wr.get();
        System.out.println("temp -- " + temp);
        while(wr.get() != null) {
            System.gc();
        }
    }
}

Ответ 7

Ну, GC всегда есть - вы не можете создавать объекты, которые находятся вне его понимания (если вы не используете собственные вызовы или не выделяете буфер прямого байта, но в последнем случае у вас действительно нет объекта, просто куча байтов). Тем не менее, безусловно, можно обойти GC путем повторного использования объектов. Например, если вам нужна группа объектов ArrayList, вы можете просто создать их по мере необходимости и позволить GC обрабатывать управление памятью; или вы можете называть list.clear() на каждом из них после того, как закончите с ним, и поместите его в какую-то очередь, где кто-то еще сможет его использовать.

Стандартные передовые методы - это не повторное использование такого рода, если у вас нет веских оснований (т.е. вы профилировали и видели, что выделение + GC является проблемой, а повторное использование объектов устраняет эту проблему). Это приводит к более сложному коду, и если вы ошибетесь, это может сделать работу GC более сложной (из-за того, как GC отслеживает объекты).

Ответ 8

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

Все остальное намеренно уходит в Java Runtime и также - преднамеренно - определяется как можно более смутно, чтобы позволить дизайнерам JVM большей свободы делать это эффективно.

Чтобы использовать аналогию: ваша операционная система управляет именованными областями пространства жесткого диска (так называемые "файлы" ) для вас. Включая удаление и повторное использование областей, которые вы больше не хотите использовать. Вы не обходите этот механизм, но оставьте его в операционной системе

Вам следует сосредоточиться на написании четкого простого кода и убедиться, что ваши объекты выполнены правильно. Это даст JVM наилучшие условия работы.

Ответ 9

Я бы посоветовал взглянуть на следующие учебники и его содержание

Это сериал из четырех частей, чтобы узнать об основах сборки мусора в Java:

  • Введение в сборку мусора Java

  • Как работает сборка мусора Java?

  • Типы сборщиков мусора Java

  • Мониторинг и анализ коллекции мусора Java

Я нашел Этот учебник очень полезен.

Ответ 10

"Обнулить" ссылку, если это не требуется, - лучший способ сделать объект, подходящий для сбора мусора.

Существует 4 способа, с помощью которых объект может быть собран Мусором. 1. укажите ссылку на нуль, как только она больше не требуется.

String s = new String("Java");

Как только эта строка не требуется, вы можете указать ей значение null.

s = null;

Следовательно, s будет иметь право на сбор мусора.

  1. укажите один объект на другой, так что обе точки привязки к одному и тому же объекту и одному из объектов имеют право на GC.

    String s1 = new String ( "Java" );

    String s2 = new String ( "С++" );

В будущем, если s2 также нужно указать на s1, то

s1 = s2;

Тогда объект, имеющий "С++", будет иметь право на GC.

  1. Все объекты, созданные в методе, имеют право на GC после завершения метода. Следовательно, как только метод будет уничтожен из стека потока, соответствующие объекты в этом методе будут уничтожены.

  2. Остров Изоляции - это еще одна концепция, в которой объекты с внутренними ссылками и внешняя ссылка на ссылку имеют право на сбор мусора. "Остров изоляции" коллекции мусора

Примеры: Ниже приведен метод класса Camera в android. Посмотрите, как разработчик указал mCameraSource на null, когда это не требуется. Это код экспертного уровня.

public void release() {
        if (mCameraSource != null) {
            mCameraSource.release();
            mCameraSource = null;
        }
    }

Как работает сборщик мусора?
Сбор мусора выполняется потоком демона под названием Garbage Collector. Когда в это время имеется достаточное количество памяти, этот поток демонов имеет низкий приоритет и работает в фоновом режиме. Но когда JVM обнаруживает, что куча заполнена, и JVM хочет вернуть некоторую память, тогда она увеличивает приоритет потока коллектора Garbage и вызывает метод Runtime.getRuntime.gc(), который ищет все объекты, которые не имеют ссылочной или нулевой ссылки, и уничтожает эти объекты.