Пытаясь понять сборку мусора в Java - PullRequest
1 голос
/ 12 мая 2019

Пытаясь понять GC с помощью приведенного ниже куска кода

public class Test1 {
    public static void main(String[] args) {

        //HashMap<String,String> newmap = new HashMap<String,String>();
        //CleanUpThread t = new CleanUpThread(newmap);
        ArrayList<Double> al = new ArrayList<Double>();
        //t.start();
        while(true){

            al.add(Math.random());


            try {
                Thread.currentThread().sleep(200);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }


    }
}

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

Но я вижу, что мой GC очищается, и только ~ 1 МБ данных остается в пространстве для выживших.

Запуск jvm с размером кучи 32 МБ и% заполнения для GC, установленным на 30%.

Может ли кто-нибудь дать более подробное объяснение поведения. enter image description here

Ответы [ 2 ]

3 голосов
/ 12 мая 2019

Прежде всего, вы не появлялись OutOfMemoryError, потому что объекты в вашем коде создаются очень медленно (каждые 200 мс).Попробуйте удалить sleep фрагмент кода.

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

enter image description here

Когда ваш размер кучи будет заполнен, GCбудет пытаться очистить объекты (вы увидите часто колебания на временной диаграмме ГХ), но эти попытки будут безуспешными, потому что не будет объектов для удаления.Со временем вы получите OME.

Я думаю, что если вы удалите фрагмент кода sleep и подождете достаточно времени, вы получите OME.

Для более быстрых результатов вы можете уменьшить размер кучи.

0 голосов
/ 12 мая 2019

всякий раз, когда вы заполняете пространство Eden, запускается Minor GC, и он передает живые объекты выжившему.После некоторой итерации долгоживущие оставшиеся в живых объекты переносятся в старое пространство Generation.

В вашем случае вспомогательный GC запускается всякий раз, когда пространство Eden исчерпывается до процента, а размер старого поколения увеличивается со временем.,Вы можете изобразить это на графике.

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

Для большего понимания вы можете обратиться к https://www.journaldev.com/2856/java-jvm-memory-model-memory-management-in-java

...