Подтвердить что ты не робот

Java 8 выделяет слишком много памяти

Я запускаю Eclipse 4.3 с Java 7 JRE. Когда я обновляюсь до Java 8 JRE, Eclipse внезапно потребляет больше памяти. Если я запустил Eclipse с JRE 7 прямо в мое рабочее пространство, он выделяет 600 МБ ОЗУ в соответствии с Диспетчером задач. Когда я использую JRE 8, это значение составляет 750 МБ.

Хуже того, если я запускаю большую программу Java, которая обычно выделяет около 10 ГБ ОЗУ с помощью JRE 7, переход на JRE 8 заставляет его выделять 12 ГБ ОЗУ.

Кто-нибудь знает, что вызывает это дополнительное распределение ОЗУ? Я тестировал различные варианты, но с нулевым успехом:

-XX:ReservedCodeCacheSize=
-XX:MaxMetaspaceSize=
-XX:MetaspaceSize=
...
4b9b3361

Ответ 1

Как задается вопрос

почему Java 8 выделяет слишком много памяти на моей машине

Я не думаю, что кто-нибудь сможет ответить, однако есть несколько рекомендаций, которые могут помочь. Учитывая, что вы измеряете память через диспетчер задач, вас интересует общий используемый RSS. Так

  • Шаг 1: Сравните значения по умолчанию JVM между версией, которую вы используете. Вы можете получить их с помощью команды java -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version для обоих jdks. Используя сортировку текста в верхней части вывода, вы сможете получить хороший diff, используя любой инструмент сравнения. Такие вещи, как изменение коллектора GC коллектора и размера стека потоков, очень сильно повлияют на окончательный RSS.
  • Шаг 2: Измерьте распределение для каждого пула памяти. В общем случае общая память, используемая java, может быть рассчитана с использованием heap + metasize + code cache + native + (thread_stack_size * maximum_number_of_threads)
    • Память кучи легко измерима (и может быть легко сравнима!!) зрелыми инструментами (Eclipse Memory Analyzer, VisualVM и т.д.). Если память увеличение площади кучи - вам очень повезло. В дополнительном визуальном vm вы можете установить плагин, который будет отображать значения всех пулов памяти, доступных через jmx.
    • metasize (aka permgen in jdk < 8) должен быть более/менее равным и может быть найден с помощью инструмента jmap. Нет необходимости играть с флагом, вы можете получить номер и просто сравнивать каждый раз, когда он увеличивается или нет.
    • Кэш кеша: помимо зарезервированного кеша кода вы можете установить начальный кеш кода (и это повлияет на то, сколько RSS используется).
    • native: это немного черных овец. Если все остальные пулы памяти равны (память падает на 2 ГБ), потерянная память должна быть где-то в родной области. Единственный инструмент, о котором я знаю, - jcmd, и он имеет обширную документацию в документах oracle.

Нетехнические - в то время как настройка различных вариантов для уменьшения памяти может помочь, шансы получить правильные значения близки к поиску иглы в стоге сена. Я бы порекомендовал иметь о том, как RSS используется в java. Это знание будет полезно в течение нескольких лет!

Пожалуйста, дайте мне знать, когда вам нужны более конкретные ссылки или лучшее объяснение. И... удачи в твоем квете; -)

Ответ 2

Я могу подтвердить, что веб-приложение, над которым я работаю (Jetty, Struts2, JDBC), потребляет около 300 МБ больше ОЗУ (1.2G) сразу после запуска при работе в JRE 1.8.0_72 по сравнению с JRE 1.7.0_80. Приложение работает на Centos 6 x64 и делает измерения памяти максимально прозрачными. Я отключил swap и установил -Xms равным -Xmx (40% доступной ОЗУ). Я использовал dstat --top-mem или top -m, чтобы получить общую память, потребляемую java-процессом.

Кроме того, когда веб-клиенты слишком часто подключаются к приложению, общая потребленная память увеличивается до тех пор, пока система не выйдет из памяти и не уничтожит процесс Java. Единственное, что я вижу, это информация в /var/log/messages:

Ноя 10 21:29:54 мое ядро: Недостаточно памяти: Убей процесс 26610 (java) набрать 570 или жертвовать ребенком

Когда я запускаю бесконечный цикл из bash, который вызывает 4 параллельных веб-клиента, подключающихся к приложению (= установить новое TCP-соединение), запрашивает статус приложения и отключается, тогда общая память, потребляемая приложением, увеличивается примерно на 100- 200 КБ каждая минута. Каждый клиент выполняет 6-10 запросов в минуту. Размер памяти кучи стабилен.