Тест проверки памяти процесса Java

Я пытался увидеть, как параметры -Xmx и -Xms влияют на мою программу и проверяют, сколько памяти потребляет мой процесс.

Я написал простую программу, но не могу разгадать результаты. Просьба помочь.

public static void main( String[] args ) {
        char[] array = new char[69926904];
}

Я работал с параметрами -Xms5M -Xmx200M. В идеале, поскольку символ принимает 2 байта, он должен содержать 100M символов перед превышением предела памяти. Даже если мы говорим, что мало места используется для указателя и длины, я не знаю, почему он бросает ошибку после длины 69926904.

Спасибо.

Ответ 1

Внимательно прочитайте Руководство по настройке коллекции мусора JVM о Generational Heap, и он, надеюсь, ответит на ваш вопрос.

Запустите Java с параметром -XX:+PrintGCDetails, и все должно стать ясным:

Heap
 PSYoungGen      total 3584K, used 294K [0x00000000fbd60000, 0x00000000fc160000, 0x0000000100000000)
  eden space 3072K, 9% used [0x00000000fbd60000,0x00000000fbda9860,0x00000000fc060000)
  from space 512K, 0% used [0x00000000fc0e0000,0x00000000fc0e0000,0x00000000fc160000)
  to   space 512K, 0% used [0x00000000fc060000,0x00000000fc060000,0x00000000fc0e0000)
 PSOldGen        total 136576K, used 136576K [0x00000000f3800000, 0x00000000fbd60000, 0x00000000fbd60000)
  object space 136576K, 100% used [0x00000000f3800000,0x00000000fbd60000,0x00000000fbd60000)
 PSPermGen       total 21248K, used 2595K [0x00000000ee600000, 0x00000000efac0000, 0x00000000f3800000)
  object space 21248K, 12% used [0x00000000ee600000,0x00000000ee888db0,0x00000000efac0000)

Ваша 200M Java Heap состоит из двух поколений: 1/3 (66.7M) - YoungGen и 2/3 (133.3M) - OldGen.

Опция

-XX:NewRatio позволяет изменить пропорцию, но значение по умолчанию 2 означает, что YoungGen зарезервирует 1/(2 + 1) часть кучи.

Объекты Java не могут охватывать поколения, поэтому максимальный размер объекта не может быть больше самого большого поколения. В вашем случае самым большим поколением является OldGen: 136576K = 139853824, который является точно размером char[69926904] (16 байтов в заголовке + 2 * 69926904 байта данных).

Ответ 2

Эта информация взята из страницы "Оракулы" на странице Настройка коллекции мусора с виртуальной машиной 5.0 Java [tm].

Куча и поколения

Сначала важно знать, как работает куча. Как вы знаете, объекты (например, ваш массив) хранятся в куче. Однако куча - это не одно равномерное пространство. Он фактически разделен на три поколения, а именно Young, Настроенный и Постоянный.

Сбор мусора происходит в каждом поколении, когда поколение заполняется. Объекты сначала выделяются в молодое поколение, и из-за младенческой смертности большинство объектов умирают там. Некоторые выжившие объекты перемещаются в поколение. Когда нужно собирать поколение, существует большая коллекция, которая часто намного медленнее, потому что она включает в себя все живые объекты.

"Молодое поколение состоит из эдена и двух оставшихся в живых. Объекты изначально выделяются в eden. Один оставшийся в живых в любое время, и служит в качестве места назначения следующего, копирования сбор любых живых объектов в эдене и в другом оставшемся в живых пространстве. Таким образом, объекты копируются между оставшимися в живых пространствами до тех пор, пока они не будут достаточно старых, чтобы их можно было использовать или скопировать в поколение".

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

Некоторые параметры

В дополнение к параметрам -Xms и -Xmx, которые управляют общим размером кучи, существуют параметры, которые управляют размером отдельных сегментов. В вашем примере вы устанавливали максимальный размер кучи, но вы все еще использовали коэффициент генерации по умолчанию.

"По умолчанию размер молодого поколения контролируется NewRatio. например, установка -XX: NewRatio = 3 означает, что соотношение между молодыми и поколение поколений - 1: 3. Другими словами, совокупный размер эден и оставшиеся в живых места будут составлять одну четверть от общей кучи размер".

Проблема

"В идеальной небольшой коллекции живые объекты копируются из одного часть молодого поколения (пространство с эденом плюс первый выживший космос) в другую часть молодого поколения (второй выживший пространство). Однако нет никакой гарантии, что все живые объекты будут вписываются во второе пространство для оставшихся в живых. Для обеспечения того, чтобы несовершеннолетний сбор может завершаться, даже если все объекты живут, достаточно бесплатно память должна быть зарезервирована в поколенном поколении для размещения всех живые объекты. В худшем случае эта зарезервированная память равна размер эдена плюс объекты в непустоте оставшегося в живых. когда в этом поколении недостаточно памяти для этого В худшем случае вместо этого будет создана большая коллекция.

То, что вы пытаетесь сделать, - это хранить один огромный массивный объект. Этот объект должен вписываться в одно из поколений, и просто нет достаточно большого поколения. Даже если общий размер кучи больше, чем объект, это не помогает, потому что объекты не могут охватывать несколько поколений.

Что попробовать

Попробуйте добавить следующий параметр при запуске кода: -XX:NewRatio=10. Как описано выше, это сделает поколение в десять раз большим, чем молодое поколение. В результате гораздо более крупный объект сможет вписаться в поколение поколений.

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