Я использую JVM для научного приложения. Первым шагом в моем процессе является загрузка большого количества данных в маленькие массивы double[]
(массивы из 48 элементов для каждого узла в большом графе). Задолго до того, как я узнаю, достаточно ли у меня памяти, чтобы загрузить их все, Java асимптотически замедляется, и jvisualvm говорит мне, что это связано с тем, что почти все время процессора тратится на сборку мусора:
Первая минута или около того в порядке: «использованная куча» (правый график) прыгает вверх и вниз по мере роста, потому что некоторые объекты являются временными (я написал это на Scala), а некоторые объекты являются постоянными. Однако после этого загрузка данных останавливается, потому что сборщик мусора, по-видимому, снова и снова проверяет одни и те же объекты (левый график). Должно быть, ожидается, что они выйдут за рамки, но я оставляю их в рамках, потому что хочу использовать их для своего анализа.
Я знаю, что сборщик мусора помещает объекты в разные поколения, исходя из их вероятности выживания. Первое поколение содержит недавно созданные объекты, которые, вероятно, скоро исчезнут; более поздние поколения имеют все больше шансов быть долгожителями. Если мои объекты ошибочно относятся к первому поколению, есть ли способ сообщить сборщику мусора, что они должны принадлежать к более позднему поколению? Я знаю, что сохраню их --- как мне сказать об этом сборщику мусора?
Хотя я бы хотел, чтобы эти объекты были в более постоянном поколении, PermGen был бы слишком далеко: в конце концов они умрут после десятков минут обработки. (Я хочу использовать это в редукторе Hadoop, который может работать с другим фрагментом данных после этого без новой JVM.)
Примечание. Я использую виртуальную машину Sun HotSpot:
% java -version
java version "1.6.0_45"
Java(TM) SE Runtime Environment (build 1.6.0_45-b06)
Java HotSpot(TM) 64-Bit Server VM (build 20.45-b01, mixed mode)
Исправление (к предыдущему редактированию): изменение -Xmx
действительно изменяет точку насыщения, но очевидно, что Java игнорирует аргумент командной строки -Xmx
, если он передается после аргумента -jar
. То есть сделать
java -Xmx2048 -jar MyJarFile.jar
скорее, чем
java -jar MyJarFile.jar -Xmx2048
Из-за этого я неправильно диагностировал поведение в отношении максимальной кучи, и все ответы, указывающие на флаг -Xmx
, действительны.
Точка насыщения, которую я описываю, происходит, когда «размер кучи» (оранжевый на правом графике) достигает выбранного предела -Xmx
, а «размер кучи» всегда примерно в 1,6 раза больше «используемой кучи» (синий на правом графике), если вы явно не установили размер «Старого» поколения с -XX:NewRatio
или -XX:OldSize
. Они также должны быть перед аргументом -jar
, и они обеспечивают большой контроль.