Я замечаю, что график не наклоняется строго вверх до падения, но имеет меньшие локальные вариации. Хотя я не уверен, я не думаю, что использование памяти показало бы эти небольшие потери, если бы не было никакого сбора мусора.
В Java есть второстепенные и крупные коллекции. Незначительные коллекции встречаются часто, тогда как крупные коллекции встречаются реже и еще больше снижают производительность. Незначительные коллекции, вероятно, имеют тенденцию поглощать такие вещи, как кратковременные экземпляры объектов, созданные внутри методов. Большая коллекция удалит намного больше, что, вероятно, произошло в конце вашего графика.
Теперь, некоторые ответы, которые были опубликованы, пока я набираю это, дают хорошие объяснения относительно различий в сборщиках мусора, поколениях объектов и многом другом. Но это по-прежнему не объясняет, почему до серьезной очистки потребуется так много времени (почти 24 часа).
Две вещи, которые могут быть установлены для JVM при запуске, - это максимально допустимый размер кучи и начальный размер кучи. Максимальный предел - это жесткое ограничение. После того, как вы его достигнете, дальнейшая сборка мусора не уменьшит использование памяти, и если вам потребуется выделить новое пространство для объектов или других данных, вы получите OutOfMemoryError. Тем не менее, внутри есть и мягкое ограничение: текущий размер кучи. JVM не сразу поглощает максимальный объем памяти. Вместо этого он начинается с вашего первоначального размера кучи, а затем увеличивает кучу, когда это необходимо. Подумайте об этом как о памяти вашего JVM, которая может динамически увеличиваться.
Если фактическое использование памяти вашим приложением начинает достигать текущего размера кучи, сборка мусора обычно инициируется. Это может уменьшить использование памяти, поэтому увеличение размера кучи не требуется. Но также возможно, что приложению в настоящее время нужна вся эта память, и она будет превышать размер кучи. В этом случае он увеличивается при условии, что он еще не достиг максимального установленного предела.
Итак, в вашем случае начальный размер кучи устанавливается равным максимальному. Предположим, что так и будет, тогда JVM немедленно захватит всю эту память. Это займет очень много времени, прежде чем приложение накопит достаточно мусора, чтобы достичь размера кучи при использовании памяти. Но в этот момент вы увидите большую коллекцию. Начиная с достаточно маленькой кучи и позволяя ей расти, использование памяти ограничено только тем, что необходимо.
Предполагается, что на графике показано использование кучи, а не выделенный размер кучи. Если это не так, и вы на самом деле видите, как сама куча растет, происходит что-то еще. Я признаю, что недостаточно разбираюсь во внутренних возможностях сбора мусора и его планировании, чтобы быть абсолютно уверенным в том, что здесь происходит, в основном это связано с наблюдением утечек приложений в профилировщиках. Поэтому, если я предоставил неверную информацию, я возьму этот ответ.