Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > System.gc() как она работает?


Автор: Mirkes 21.5.2014, 15:45
День добрый!
В очередной раз столкнулся с переполнением памяти.
В цикле выполняется вызов нескольких методов, которые потребляют память довольно сильно, но по выходе из метода ничего не остается (метод проводит запись в файл и освобождает память).
Решил поискать причину.
Поставил вывод состояния памяти (freeMemory()) перед вызовом каждого метода. Для чистоты решил вызвать очистку памяти (garbage collectior) перед циклом.
Код

                    for (int i = 0; i < 1; i++)
                        System.gc();
                    System.out.println(nam + "\tleading\t" + Runtime.getRuntime().freeMemory());
                    testSym(leading, nam + "\tLeading\tLeading", bw);
                    System.out.println(nam + "\tleading-lagging\t" + Runtime.getRuntime().freeMemory());
                    testAsym(leading, lagging, nam + "\tLeading\tLagging", bw2);
                    System.out.println(nam + "\tlagging-leading\t" + Runtime.getRuntime().freeMemory());
                    testAsym(lagging, leading, nam + "\tLagging\tLeading", bw2);
                    System.out.println(nam + "\tlagging\t" + Runtime.getRuntime().freeMemory());
                    testSym(lagging, nam + "\tLagging\tLagging", bw);
                    System.out.println(nam + "\tany\t" + Runtime.getRuntime().freeMemory());
                    testSym(markers, nam + "\tAny\tAny", bw);
                    testDensity(leading, lagging, markers, nam, bw3);


Что делает каждый метод пока не важно.
Вот результат
Код

SpnIIIA    leading    1,352,856,072
SpnIIIA    leading-lagging    932,057,224
SpnIIIA    lagging-leading    459,906,672
SpnIIIA    lagging    419,160,360
SpnIIIA    any    160,615,400
SpnIIIB    leading    1,388,793,904
SpnIIIB    leading-lagging    1,063,269,136
SpnIIIB    lagging-leading    893,333,104
SpnIIIB    lagging    64,591,032
SpnIIIB    any    729,938,008
SpnIIIC    leading    25,262,200
SpnIIIC    leading-lagging    125,431,008
SpnIIIC    lagging-leading    483,853,344
SpnIIIC    lagging    188,031,880
SpnIIIC    any    1,219,963,640
SpnIIID    leading    1,314,961,976
SpnIIID    leading-lagging    699,566,248
SpnIIID    lagging-leading    493,366,280
runtime error


Тогда я решил усилить очистку памяти и заменил в первой строке 1 на 10
Код

                    for (int i = 0; i < 10; i++)
                        System.gc();
                    System.out.println(nam + "\tleading\t" + Runtime.getRuntime().freeMemory());
                    testSym(leading, nam + "\tLeading\tLeading", bw);
                    System.out.println(nam + "\tleading-lagging\t" + Runtime.getRuntime().freeMemory());
                    testAsym(leading, lagging, nam + "\tLeading\tLagging", bw2);
                    System.out.println(nam + "\tlagging-leading\t" + Runtime.getRuntime().freeMemory());
                    testAsym(lagging, leading, nam + "\tLagging\tLeading", bw2);
                    System.out.println(nam + "\tlagging\t" + Runtime.getRuntime().freeMemory());
                    testSym(lagging, nam + "\tLagging\tLagging", bw);
                    System.out.println(nam + "\tany\t" + Runtime.getRuntime().freeMemory());
                    testSym(markers, nam + "\tAny\tAny", bw);
                    testDensity(leading, lagging, markers, nam, bw3);


Вот результат
Код

SpnIIIA    leading    11,274,752
SpnIIIA    leading-lagging    356,311,560
SpnIIIA    lagging-leading    72,682,840
SpnIIIA    lagging    99,125,392
SpnIIIA    any    1,285,621,904
SpnIIIB    leading    24,562,688
SpnIIIB    leading-lagging    228,589,728
SpnIIIB    lagging-leading    432,159,112
SpnIIIB    lagging    271,199,552
SpnIIIB    any    78,527,800
SpnIIIC    leading    24,396,856
SpnIIIC    leading-lagging    80,807,584
SpnIIIC    lagging-leading    642,683,672
SpnIIIC    lagging    69,728,504
SpnIIIC    any    1,253,885,984
SpnIIID    leading    24,390,328
SpnIIID    leading-lagging    486,687,648
SpnIIID    lagging-leading    566,679,216
runtime error


У меня возникло подозрение, что gc() просто стартует, а управление немедленно возвращается вызвавшему методу. Это действительно так?

Автор: LSD 21.5.2014, 18:00
Вместо
Код

System.out.println(nam + "\tany\t" + Runtime.getRuntime().freeMemory());

лучше использовать флаги -XX:+PrintGCDateStamps -XX:+PrintGCDetails.

Для того чтобы посмотреть, какие объекты занимают память, надо использовать профилировщики, например Java VisualVM (идет в комплекте с JDK).

Добавлено через 3 минуты и 42 секунды
Цитата(Mirkes @  21.5.2014,  16:45 Найти цитируемый пост)
У меня возникло подозрение, что gc() просто стартует, а управление немедленно возвращается вызвавшему методу. Это действительно так? 

Это сложный вопрос, так просто на него не ответишь. Вобще говоря, вызов gc() может вообще ничего не делать о чем прямо говориться в документации, но пока все таки он инициирует сборку мусора. Если дергать его часто и памяти достаточно, то с большой долей вероятности будет собираться лишь young generation и это бует просисходить быстро.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)