Сборка мусора на Java
Вступление
Управление памятью - это процесс распознавания, когда выделенные объекты больше не нужны, освобождения (освобождения) памяти, используемой такими объектами, и предоставления ее для последующих распределений. В некоторых языках программирования за управление памятью отвечает программист. Общая проблема с явным управлением памятью - утечки пространства. Эти утечки происходят, когда память выделена и больше не ссылается, но не освобождается. Альтернативный подход к управлению памятью, который в настоящее время обычно используется, особенно в большинстве современных объектно-ориентированных языков, - это автоматическое управление с помощью программы, называемой сборщиком мусора.
Преимущество сбора мусора:
Сборка мусора освобождает программистов от бремени освобождения выделенной памяти. Зная, когда явно освободить выделенную память, может быть очень сложно. Предоставление этой работы JVM имеет несколько преимуществ.
Сборщик мусора отвечает за
- Выделение памяти
- Обеспечение того, чтобы все упомянутые объекты оставались в памяти, и
- Восстановление памяти, используемой объектами, которые больше не доступны по ссылкам при выполнении кода.
Корни сбора мусора - источник всех объектных деревьев
Каждое дерево объектов должно иметь один или несколько корневых объектов. Пока приложение может достичь этих корней, все дерево достижимо. Но когда эти корневые объекты считаются достижимыми? Специальные объекты, называемые корнями сборки мусора (корни GC; см. Рисунок ниже), всегда доступны, как и любой объект, имеющий корень сборки мусора в своем собственном корне.
В Java есть четыре вида корней GC:
- Локальные переменные поддерживаются стеком потока. Это не реальная виртуальная ссылка на объект, и поэтому она не видна. Для всех намерений и целей локальные переменные являются корнями GC.
- Активные потоки Java всегда считаются живыми объектами и поэтому являются корнями GC. Это особенно важно для локальных переменных потока.
- На статические переменные ссылаются их классы. Этот факт делает их фактическими корнями GC. Сами классы можно собирать мусором, что приведет к удалению всех указанных статических переменных. Это имеет особое значение, когда мы используем серверы приложений, контейнеры OSGi или загрузчики классов в целом. Мы обсудим связанные проблемы в разделе «Образцы проблем».
- Ссылки JNI - это объекты Java, созданные собственным кодом как часть вызова JNI. Созданные таким образом объекты обрабатываются специально, потому что JVM не знает, на что ссылается нативный код или нет. Такие объекты представляют собой особую форму корня GC.
Поколение кучи для сборки мусора в Java
Java-объекты создаются в куче, а куча делится на три части или поколения для сбора мусора в Java, они называются молодым поколением, постоянным или старым поколением и пермской областью кучи.
В типичном приложении большинство объектов очень недолговечны. С другой стороны, некоторые объекты сохраняются очень долго и даже до тех пор, пока приложение не будет закрыто. При использовании сбора мусора поколений область кучи делится на две области - молодое поколение и старое поколение - которые собирают мусор с помощью отдельных стратегий. Объекты обычно создаются в молодом районе. После того, как объект пережил пару циклов ГХ, он передается старому поколению.
Новое поколение далее делится на три части, известные как пространство Eden, Survivor 1 и Survivor 2. Когда объект, впервые созданный в куче, создается в новом поколении внутри пространства Eden и после последующей незначительной сборки мусора, если объект выживает, его перемещают в
оставшийся в живых 1 и затем Оставшийся в живых 2 до того, как главный сборщик мусора перенес этот объект в старое или постоянное поколение.
Постоянное генерирование Heap или Perm Area of Heap является чем-то особенным и используется для хранения метаданных, связанных с классами и методами, в JVM, а также для размещения пула строк, предоставляемого JVM.
Полный сборщик мусора и одновременная сборка мусора на Java
Параллельный сборщик мусора в java использует один поток сборщика мусора, который работает одновременно с потоками приложения с целью завершения сбора заимствованного поколения до его заполнения. В обычной работе параллельный сборщик мусора может выполнять большую часть своей работы с работающими потоками приложения, поэтому потоки приложения видят только короткие паузы. В противном случае, если одновременный сборщик мусора не может завершить работу до того, как заполненное время пребывания заполнится, приложение будет приостановлено, и сбор будет завершен с остановкой всех потоков приложения. Такие коллекции с остановленным приложением называются полными сборками мусора или полным сборщиком мусора и являются признаком того, что необходимо внести некоторые изменения в параметры одновременной сборки. Всегда старайтесь избегать или минимизировать полную сборку мусора или полный сборщик мусора, поскольку это влияет на производительность приложения Java. Когда вы работаете в области финансов для электронной торговой платформы и с большими объемами систем с низкой задержкой, производительность java-приложения становится чрезвычайно критичной, и вам определенно нравится избегать полного GC в течение торгового периода.
Пример сборки мусора и управления памятью с использованием Java-кода. В приведенном ниже коде мы проверяем объем памяти до создания массива из 10000 строк, после его создания, после инициализации и после перераспределения всех объектов. Использование памяти печатается после каждого этапа.
Java-код: перейти к редактору
public class MemoryDemo {
public static void main(String[] args) throws InterruptedException {
Runtime r = Runtime.getRuntime();
long mem1, mem2;
String someints[] = new String[10000];
System.out.println("Total memory is: " + r.totalMemory());
mem1 = r.freeMemory();
System.out.println("Initial free memory: " + mem1);
r.gc();
mem1 = r.freeMemory();
System.out.println("Free memory after garbage collection: " + mem1);
for (int i = 0; i < 10000; i++)
someints[i] = i+""; // allocate integers
mem2 = r.freeMemory();
System.out.println("Free memory after allocation: " + mem2);
System.out.println("Memory used by allocation: " + (mem1 - mem2));
// discard Integers
for (int i = 0; i < 10000; i++)
someints[i] = null;
r.gc(); // request garbage collection
Thread.sleep(100);
mem2 = r.freeMemory();
System.out.println("Free memory after collecting discarded String: " + mem2);
}
}
Выход:
(ваш вывод может очень соответствовать версии JVM и ОС)
Резюме:
- Java Heap делится на три поколения ради сборки мусора. Это молодое поколение, штатное или старшее поколение, а также Пермский край.
- Новые объекты создаются в молодом поколении, а затем перемещаются в старое поколение.
- Пул строк создается в области Перми в куче, сборка мусора может происходить в области перми, но зависит от JVM до JVM.
- Незначительная сборка мусора используется для перемещения объекта из пространства Eden в пространство Survivor 1 и Survivor 2, а коллекция Major - для перемещения объекта из поколения в поколение.
- Всякий раз, когда происходит крупный сбор мусора, потоки приложений останавливаются в течение этого периода, что снижает производительность и пропускную способность приложения.
- В сборке мусора в java 6 было сделано несколько улучшений производительности, и мы обычно используем JRE 1.6.20 для запуска нашего приложения.
- Параметры командной строки JVM –Xmx и -Xms используются для настройки начального и максимального размера Java Heap. Идеальное соотношение этого параметра - 1: 1 или 1: 1,5, исходя из моего опыта, например, вы можете выбрать либо –Xmx, либо –Xms как 1 ГБ, либо –Xms 1,2 ГБ и 1,8 ГБ.
- В Java нет ручного способа сбора мусора
Редактор кода Java:
Предыдущий: метод valueOf
Далее: метод BigDecimal
Новый контент: Composer: менеджер зависимостей для PHP , R программирования