Зачем нужен пилообразный график?
Когда я запускаю приведенный ниже код (используя netbeans), выделенный размер кучи изменяется в пилообразной форме. Я прикрепляю захват от jVisualVM, который показывает используемый кучевой график в пилообразной форме. Программа представляет собой простой бесконечный цикл печать "lol" на выводе.
class one{
static int i=0;
public static void main(String a[]){
while(i<10){
System.out.println("lol");
}
}
}
Может ли кто-нибудь объяснить причину формы графика используемой кучи?
ps: это происходит, даже если я запускаю его без использования NetBeans, поэтому он несколько не связан с netbeans...
Ответы
Ответ 1
Пильный рисунок в использовании кучи можно объяснить тем, что при вызове вызова System.out.println
создается несколько локальных переменных. В частности, в Oracle/Sun JRE несколько экземпляров HeapCharBuffer
создаются в молодом поколении, как указано в следующем снимке, полученном с использованием профилировщика памяти VisualVM:
![Visual VM - Memory snapshot]()
Интересный бит - количество живых объектов, которые присутствуют в куче. Пилообразный рисунок получается из цикла сбора мусора молодого поколения, который возникает, когда пространство эден заполняется; поскольку в программе нет тяжелой вычислительной активности, JVM может выполнять несколько итераций цикла, в результате чего заполняется пространство eden (размером 4 МБ). Последующий цикл сбора молодого поколения затем очищает большую часть мусора; это почти всегда все пространство eden, если только объекты еще не используются, о чем свидетельствует следующая следа gc, полученная из VisualVM:
![Visual VM GC probes]()
Таким образом, поведение пилообразного паттерна может быть объяснено серией распределений объектов в быстрой последовательности, которые заполняют пространство эден, вызывая цикл сбора мусора молодого поколения; этот процесс циклически повторяется без каких-либо задержек, поскольку основной процесс JVM не вытесняется другим процессом, а основной поток в JVM, который отвечает за распределение объектов, также не вытесняется другим потоком.
Ответ 2
Любой процесс, распределяющий объекты с регулярной скоростью, приведет к постоянному увеличению потребления памяти кучи, а затем мгновенным падениям, когда сборщик мусора собирает ненужные объекты, что приводит к тому, что пилообразная форма.
В случае, если вы задаетесь вопросом, почему ваш Java-процесс сохраняет выделенную память при записи на System.out
, имейте в виду, что другие потоки (например, одна из которых загружает текущую статистику памяти в JVisualVM) могут быть теми, которые выделяют память.
Ответ 3
Там может быть много мест, и это, вероятно, зависит от реализации. По крайней мере, возможны следующие (но все это просто спекуляция)
-
где-то в стеке потоков под System.out.println имеется распределение байтового массива (учитывая, что одним из основных методов выходного потока является запись (bytes [] b, int off, int len) )
-
это служебные данные, используемые используемым программным обеспечением мониторинга (я его не использовал)
-
он накладные расходы в VM netbeans, где он заканчивает показывать вывод
Ответ 4
Фактически jVisualVM вызывает дополнительное выделение объекта. jVisualVM и jconsole используют расширения Java Management Extensions. Прикрепление к запущенному приложению и запрос JVM-метрик, вызывающих создание дополнительных объектов.
Вы можете проверить это, добавив к вашему программному вызову
Runtime.getRuntime().freeMemory()
который сообщает о свободной памяти в куче JVM. Он покажет [почти] отсутствие изменения памяти, запустив ваш код, но как только вы подключите jVisualVM к вашей программе, вы увидите увеличение использования памяти.