Настройка памяти java linux

Обновлено: 04.07.2024

У меня проблема с приложением Java, работающим под Linux.

Когда я запускаю приложение, используя максимальный размер кучи по умолчанию (64 МБ), я вижу, используя приложение tops, что 240 МБ виртуальной памяти выделяются для приложения. Это создает некоторые проблемы с некоторыми другими программами на компьютере, которые относительно ограничены в ресурсах.

Насколько я понимаю, зарезервированная виртуальная память не будет использоваться в любом случае, потому что, как только мы достигаем предела кучи, создается OutOfMemoryError исключение. Я запустил одно и то же приложение под Windows и вижу, что размер виртуальной памяти и размер кучи одинаковы.

Есть ли способ настроить виртуальную память для процесса Java под Linux?

Редактировать 1 : проблема не в куче. Проблема в том, что если я установлю, например, кучу 128 МБ, Linux все равно выделит 210 МБ виртуальной памяти, которая никогда не нужна **.

Редактировать 2 : Использование ulimit -v позволяет ограничить объем виртуальной памяти. Если размер установлен ниже 204 МБ, приложение не будет работать, даже если ему не нужно 204 МБ, только 64 МБ. Поэтому я хочу понять, почему Java требует так много виртуальной памяти. Можно ли это изменить?

Редактировать 3 : в системе работает несколько других приложений, которые встроены. И система имеет ограничение виртуальной памяти (из комментариев, важные детали).

Почему вы обеспокоены использованием виртуальной памяти? Если вы действительно хотите быть обеспокоенным, посмотрите на использование резидентной памяти и прочитайте следующие команды: free, ps, top. В системе работает несколько других приложений, которые встроены. И система имеет ограничение виртуальной памяти. Какую реализацию Java вы используете. IIRC, бесплатное стандартное (не OpenJDK) решение Sun JRE не лицензировано для встроенного использования. Я думаю, что я не использовал «встроенную» часть . она ограничена в памяти и аппаратное обеспечение настроено, но это все еще стандартный компьютер

Это была давняя жалоба на Java, но она в значительной степени бессмысленна и обычно основана на поиске неверной информации. Обычная формулировка выглядит примерно так: «Hello World на Java занимает 10 мегабайт! Зачем это нужно?» Что ж, вот способ заставить Hello World на 64-битной JVM претендовать на 4 гигабайта . хотя бы одним способом измерения.

В Linux команда top выдает несколько разных чисел для памяти. Вот что говорит пример Hello World:

  • VIRT - это пространство виртуальной памяти: сумма всего на карте виртуальной памяти (см. Ниже). Это в значительной степени бессмысленно, кроме случаев, когда это не так (см. Ниже).
  • RES - это размер резидентного набора: количество страниц, которые в настоящее время находятся в оперативной памяти. Почти во всех случаях это единственное число, которое вы должны использовать, когда говорите «слишком большой». Но это все еще не очень хороший показатель, особенно если говорить о Java.
  • SHR - это объем резидентной памяти, который используется совместно с другими процессами. Для процесса Java это обычно ограничивается общими библиотеками и отображенными в память JAR-файлами. В этом примере у меня был запущен только один процесс Java, поэтому я подозреваю, что 7k - это результат использования библиотек ОС.
  • SWAP не включен по умолчанию и здесь не отображается. Он указывает объем виртуальной памяти, которая в настоящее время находится на диске, независимо от того , находится ли она на самом деле в области подкачки . Операционная система очень хорошо хранит активные страницы в оперативной памяти, и единственные способы ее замены - (1) купить больше памяти или (2) сократить количество процессов, поэтому лучше игнорировать это число.

Ситуация для диспетчера задач Windows немного сложнее. В Windows XP есть столбцы «Использование памяти» и «Размер виртуальной памяти», но в официальной документации ничего не говорится о том, что они означают. Windows Vista и Windows 7 добавляют больше столбцов, и они фактически задокументированы . Из них измерение «Рабочий набор» является наиболее полезным; это примерно соответствует сумме RES и SHR в Linux.

Виртуальная память, используемая процессом, представляет собой сумму всего, что находится в карте памяти процесса. Это включает в себя данные (например, кучу Java), а также все общие библиотеки и файлы отображения памяти, используемые программой. В Linux вы можете использовать команду pmap, чтобы увидеть все объекты, отображенные в пространстве процесса (с этого момента я буду ссылаться только на Linux, потому что это то, что я использую; я уверен, что есть эквивалентные инструменты для Windows). Вот выдержка из карты памяти программы «Hello World»; вся карта памяти имеет длину более 100 строк, и нет ничего необычного в том, чтобы иметь список из тысячи строк.

Краткое объяснение формата: каждая строка начинается с адреса виртуальной памяти сегмента. Далее следуют размер сегмента, разрешения и источник сегмента. Этот последний элемент является либо файлом, либо «anon», который указывает блок памяти, выделенный через mmap .

Начиная сверху, мы имеем

  • Загрузчик JVM (т.е. программа, которая запускается при вводе java ). Это очень мало; все, что он делает, это загружает в разделяемые библиотеки, где хранится настоящий код JVM.
  • Связка аноновых блоков, содержащих кучу Java и внутренние данные. Это Sun JVM, поэтому куча разбита на несколько поколений, каждое из которых является собственным блоком памяти. Обратите внимание, что JVM выделяет пространство виртуальной памяти на основе -Xmx значения; это позволяет ему иметь непрерывную кучу. Это -Xms значение используется внутри, чтобы сказать, сколько кучи «используется» при запуске программы, и запустить сборку мусора при приближении к этому пределу.
  • Отображаемый в память JAR-файл, в данном случае файл, содержащий «классы JDK». Когда вы отображаете JAR в память, вы можете очень эффективно обращаться к файлам в нем (вместо того, чтобы каждый раз читать его с самого начала). Sun JVM отобразит в памяти все файлы JAR на пути к классам; если вашему приложению необходим код для доступа к JAR, вы также можете отобразить его в памяти.
  • Данные по потокам для двух потоков. Блок 1M - это стек потоков. У меня не было хорошего объяснения для блока 4k, но @ericsoe идентифицировал его как «защитный блок»: у него нет разрешений на чтение / запись, поэтому при обращении к нему будет возникать ошибка сегмента, и JVM отлавливает это и переводит это к StackOverFlowError . Для реального приложения вы увидите десятки, если не сотни этих записей, повторенных через карту памяти.
  • Одна из разделяемых библиотек, которая содержит реальный код JVM. Есть несколько из них.
  • Общая библиотека для стандартной библиотеки C. Это только одна из многих вещей, которые загружает JVM, которые не являются строго частью Java.

Совместно используемые библиотеки особенно интересны: каждая разделяемая библиотека имеет как минимум два сегмента: сегмент только для чтения, содержащий код библиотеки, и сегмент чтения-записи, содержащий глобальные данные о процессах для библиотеки (я не знаю, что сегмент без разрешений есть; я видел его только на x64 Linux). Часть библиотеки, доступная только для чтения, может использоваться всеми процессами, которые используют библиотеку; например, libc имеет 1,5 МБ виртуальной памяти, которую можно использовать совместно.

Карта виртуальной памяти содержит много вещей. Некоторые из них доступны только для чтения, некоторые из них являются общими, а некоторые выделяются, но никогда не затрагиваются (например, почти все 4 Гб кучи в этом примере). Но операционная система достаточно умна, чтобы загружать только то, что ей нужно, поэтому размер виртуальной памяти в значительной степени не имеет значения.

Размер виртуальной памяти важен, если вы работаете в 32-битной операционной системе, где вы можете выделить только 2 ГБ (или, в некоторых случаях, 3 ГБ) адресного пространства процесса. В этом случае вы имеете дело с дефицитным ресурсом, и вам, возможно, придется пойти на компромисс, например, уменьшить размер кучи, чтобы отобразить в памяти большой файл или создать много потоков.

Но, учитывая, что 64-битные машины распространены повсеместно, я не думаю, что пройдет много времени, прежде чем объем виртуальной памяти станет абсолютно неактуальной статистикой.

Размер резидентного набора - это та часть виртуальной памяти, которая фактически находится в ОЗУ. Если ваш RSS становится значительной частью вашей общей физической памяти, возможно, пришло время начать беспокоиться. Если ваш RSS-канал начинает занимать всю вашу физическую память, а ваша система начинает обмениваться, уже давно пора начать беспокоиться.

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

Если вы не поменялись местами, не слишком переживайте о том, что говорит вам различная статистика памяти. С оговоркой, что постоянно растущая RSS может указывать на какую-то утечку памяти.

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

Доступ к диску (т. Е. К базе данных) стоит дорого, а память - дешево. Если вы можете обменять одно на другое, сделайте это.


Как же рассчитывается Heap sizes?

Тем не менее, алгоритм что выше, как раз для справки, могут варьироваться в разных VM.

memory JVM

Обзор памяти Java

Краткий обзор структуры памяти Java:

2. Размер Perm Gen (Perm Gen Size).
Место для хранения определение загруженного класса и метаданных. Если большой кодовый, базовый проект загружен, имеет недостаточный размер Perm Gen size то это вызовит ошибку: Java.Lang.OutOfMemoryError: PermGen.

-Xss = Установить размер стека Java (java thread stack size).

ЗАМЕТКА
Значение по умолчанию для heap size, perm gen, или stack size отличаются от различных JVM. Лучшие практически всегда определить собственные значение для сервера.

ТЕСТЫ или ГОТОВЫЕ примеры

Приведу различные тесты на разных ОС.

Ubuntu

Среда тестирования имеет такие характеристики:

ОС : Ubuntu 13 (64 битная) (Под управлением VirtualBox)
RAM : 4Гб оперативной памяти
CPU : 1 x Процессор
JDK : 1.7

Выполним команду для отображения необходимой информации:

Узнать размер Java Heap Memory Size в Ubuntu

Для JVM выделено следующие значения по умолчанию:

Java heap size
InitialHeapSize = 64781184 байт (61.7 Мб) и MaxHeapSize = 1038090240 байт (990Мб).

PermGen Size
PermSize = 21757952 байт (20.75 Мб), MaxPermSize = 174063616 байт (166 Мб)

Thread Stack Size
ThreadStackSize = 1024 кб (1 Мб)

Выделенный размер кучи (heap memory size) довольно близок к результатам эргономики.

Mac OS X

Среда тестирования имеет такие характеристики:

ОС : Mac OSX 10.9
RAM : 8 Гб оперативной памяти
CPU : 4 x Поцессор
JDK : 1.7

Запускаем команду чтобы проверить:

Узнать размер Java Heap Memory Size в macOS X

Узнать размер Java Heap Memory Size в macOS X

Для JVM выделено следующие значения по умолчанию:

Java heap size
InitialHeapSize = 20655360 байт (19.69M) и MaxHeapSize = 331350016 bytes (316 Мб).

PermGen Size
PermSize = 21757952 байт (20.75 Мб), MaxPermSize = 85983232 байт (82 Мб).

Java Stack Size
ThreadStackSize = 1024 Кб (1 Мб)

Выделенный размер кучи памяти (heap memory size) не имеют никакого значения, если сравнить со следующий результат по алгоритму эргономики.

Windows
Grep нет в Windows, вместо этого, мы используем Findstr.

Среда тестирования имеет такие характеристики:

ОС : Windows 8
RAM : 16 Гб
CPU : 8 x процессор
JDK : 1.7

Узнать размер Java Heap Memory Size в windows

Узнать размер Java Heap Memory Size в windows

Для JVM в Windows ОС выделено следующие значения по умолчанию:

Java heap size
InitialHeapSize = 266634176 байт (256 Мб) и MaxHeapSize = 4266146816 байт (4068 Мб).

PermGen Size
PermSize = 21757952 байт (20.75 Мб), MaxPermSize = 85983232 bytes (823 Мб).

Java Stack Size
ThreadStackSize = 0 kilobytes. (weird…)

Выделенный размер кучи памяти почти такой же как и по алгоритму эргономика:

Предлагаемые для Java Memory

Ниже, я привел мою рекомендацию (параметры) для малой и средней нагрузки приложений Java 🙂

Heap = -Xms512m -Xmx1024m
PermGen = -XX:PermSize=64m -XX:MaxPermSize=128m
Thread = -Xss512k

P.S: Для большинства проектов Java, 512k памяти для потока (thread) более чем достаточно.

оптимаьные значения для Java Heap Memory Size

оптимаьные значения для Java Heap Memory Size

Часто задаваемые вопросы.

Что это -XX:+PrintCommandLineFlags?
Это -XX:+PrintCommandLineFlags используется для вывода значения,только для изменения VM (обозначается так: = символ).

Вывод

Наконец, значения по умолчанию для heap memory, perm gem и stack size отличается от JVM, не ожидайте что JVM будет использовать оптимальные значения для вашего приложения Java.

Добавить комментарий Отменить ответ

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.

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

Зачем увеличивать память Java

Задачу по увеличению Java памяти пользователи ставят перед собой в следующих случаях:

Как выделить память Java

Выделить Джава-модулю больше оперативной памяти возможно через «Панель управления». Способ удобнее рассмотреть на примере проблем с запуском игры Minecraft.

Инструкция:

  1. Открывается «Панель управления».
  2. В поиске нужно найти Java-модуль.
  3. После запуска ПО в шапке выбирается раздел Java.
  4. В запустившемся окне открывается View.
  5. Для корректной работы модуля удалите лишние строки, если они есть. Должна остаться только одна, где указана последняя версия ПО. Важно обратить внимание на разрядность.
  6. Для увеличения памяти производится изменение столбца Runtime Parameters. При этом параметры записываются в следующем виде: -Xincgc-Xmx2048M, где 2048 – 2 Гб выделяемой оперативки. Важно писать без пробелов. В 32-битной ОС рекомендуется выделение 768 Мб.
  7. Нажимается ОК, ОС перезагружается.
  • Xincgc – освобождает неиспользуемые объекты из памяти;
  • Xmx – максимальный объем оперативки;
  • Xms – минимальный объем.

Если это не помогло запустить Minecraft, переустановите модуль Java и игру. После удаления очистите реестр с помощью CCleaner.

Увеличение памяти с помощью переменных среды

Увеличить оперативную память в Джаве можно с помощью переменных системной среды. В виртуальной машине прописываются два аргумента, упомянутых ранее: -Xms и -Xmx.

Чтобы система воспринимала написанные аргументы, нужно добавить переменную с названием «_JAVA_OPTIONS».

Если количество памяти, отведенной для работы Java, в два раза меньше имеющейся оперативки, то команды прописываются по следующей инструкции:

системные переменные Windows

  1. Открываются «Свойства» на ярлыке «Мой компьютер».
  2. Из левой части выбираются «Дополнительные параметры системы».
  3. На вкладке «Дополнительно» производится одиночный клик по «Переменные среды».
  4. Нажимается кнопка «Создать».
  5. Имя переменной: «_JAVA_OPTIONS», аргументы: «-Xms512m -Xmx1024m».

В примере объем оперативки составлял 1 Гб.

Видео: 3 способа выделить больше памяти Java.

Таким образом в статье рассмотрено два метода увеличения оперативной памяти, выделяемой для работы Java-модуля.

у меня проблема с Java-приложением, работающим под Linux.

когда я запускаю приложение, используя максимальный размер кучи по умолчанию (64 МБ), я вижу, используя приложение tops, что 240 МБ виртуальной памяти выделены приложению. Это создает некоторые проблемы с некоторым другим программным обеспечением на компьютере, который относительно ограничен ресурсами.

зарезервированная виртуальная память все равно не будет использоваться, насколько я понимаю, потому что как только мы достигнем кучи ограничить OutOfMemoryError бросается. Я запустил то же приложение под windows, и я вижу, что размер виртуальной памяти и размер кучи похожи.

есть ли в любом случае, что я могу настроить виртуальную память, используемую для процесса Java под Linux?

изменить 1: проблема не в куче. Проблема в том, что если я установил кучу 128 МБ, например, все еще Linux выделяет 210 МБ виртуальной памяти, которая не нужна никогда.**

изменить 2: используя ulimit -v позволяет ограничить объем виртуальной памяти. Если размер установлен ниже 204 МБ, то приложение не будет работать, даже если ему не нужно 204 МБ, только 64 МБ. Поэтому я хочу понять, почему Java требует так много виртуальной памяти. Можно ли это изменить?

Edit 3: есть несколько других приложений, работающих в системе, которая встроена. И у системы есть ограничение виртуальной памяти (из комментариев, важная деталь).

это была давняя жалоба с Java, но она в значительной степени бессмысленна и обычно основана на взгляде на неправильную информацию. Обычная фразировка-это что-то вроде "Hello World на Java занимает 10 мегабайт! Зачем ему это нужно?"Ну, вот способ сделать Hello World на 64-битной претензии JVM, чтобы занять 4 гигабайта . по крайней мере, по одной форме измерения.

  • VIRT-это пространство виртуальной памяти: сумма всего на карте виртуальной памяти (см. ниже). Это в значительной степени бессмысленно, за исключением случаев, когда это не так (см. ниже).
  • RES-размер резидентного набора: количество страниц, которые в настоящее время находятся в ОЗУ. Почти во всех случаях это единственное число, которое вы должны использовать, говоря "слишком большой."Но это все еще не очень хорошее число, особенно когда речь идет о Java.
  • SHR-это объем резидентной памяти, которая используется совместно с другими процессами. Для процесса Java это обычно ограничивается общими библиотеками и сопоставленными с памятью JARfiles. В этом примере у меня был только один процесс Java, поэтому я подозреваю, что 7k является результатом библиотек, используемых ОС.
  • SWAP по умолчанию не включен и не отображается здесь. Он указывает объем виртуальной памяти, который в настоящее время резидент на диске,является ли это на самом деле в пространстве подкачки. ОС очень хорошо поддерживает активные страницы в ОЗУ, и единственными средствами для замены являются (1) покупка больше памяти или (2) уменьшение количества процессов, поэтому лучше игнорировать это число.

ситуация для диспетчера задач Windows немного сложнее. В Windows XP есть столбцы" использование памяти "и" размер виртуальной памяти", но официальный документация молчит о том, что они означают. Windows Vista и Windows 7 добавляют больше столбцов, и они на самом деле документирована. Из них измерение "рабочего набора" является наиболее полезным; оно примерно соответствует сумме RES и SHR в Linux.

виртуальная память, потребляемая процессом, - это общая сумма всего, что находится на карте памяти процесса. Это включает в себя данные (например, кучу Java), но и все динамические библиотеки и отображенные в память файлы используются в программе. В Linux вы можете использовать pmap команда, чтобы увидеть все вещи, отображенные в пространство процесса (отсюда я буду ссылаться только на Linux, потому что это то, что я использую; я уверен, что есть эквивалентные инструменты для Windows). Вот отрывок из карты памяти программы "Hello World"; вся карта памяти имеет длину более 100 строк, и нет ничего необычного в том, чтобы иметь список из тысячи строк.

A краткое объяснение формата: каждая строка начинается с адреса виртуальной памяти сегмента. За этим следует размер сегмента, разрешения и источник сегмента. Этот последний элемент является либо файлом, либо "anon", что указывает на блок памяти, выделенный через вызов mmap.

начиная с самого верха, у нас есть

  • загрузчик JVM (т. е. программа, которая запускается при вводе java ). Это очень мало; все, что он делает, это загрузка в общий библиотеки, где хранится реальный код JVM.
  • куча блоков anon, содержащих кучу Java и внутренние данные. Это Sun JVM, поэтому куча разбивается на несколько поколений, каждое из которых является собственным блоком памяти. Обратите внимание, что JVM выделяет пространство виртуальной памяти на основе -Xmx значение; это позволяет ему иметь непрерывную кучу. The -Xms value используется внутренне, чтобы сказать, сколько кучи "используется" при запуске программы и запускать сборку мусора как это предела.
  • сопоставленный с памятью JARfile, в этом случае файл, содержащий " классы JDK."Когда вы составляете карту памяти банки, вы можете получить доступ к файлам внутри нее очень эффективно (по сравнению с чтением с самого начала каждый раз). Sun JVM будет сопоставлять все банки на пути к классам; если вашему коду приложения нужно получить доступ к банку, вы также можете сопоставить его с памятью.
  • данные по каждому потоку для двух потоков. Блок 1M-это стек потоков; я не знаю, что входит в блок 4K. Для реального приложения вы увидите десятки, если не сотни этих записей, повторяющихся через карту памяти.
  • одна из общих библиотек, которая содержит фактический код JVM. Их несколько.
  • общая библиотека для стандартной библиотеки языка Си. Это всего лишь одна из многих вещей, которые загружает JVM, которые не являются строго частью Java.

общие библиотеки особенно интересны: каждая общая библиотека имеет по крайней мере два сегмента: только для чтения сегмент, содержащий код библиотеки, и сегмент чтения и записи, содержащий глобальные данные для каждого процесса для библиотеки (я не знаю, что такое сегмент без разрешений; я видел его только на x64 Linux). Часть библиотеки, доступная только для чтения, может совместно использоваться всеми процессами, использующими библиотеку; например, libc имеет 1,5 м пространства виртуальной памяти, которое может быть общим.

карта виртуальной памяти содержит много вещей. Некоторые из них доступны только для чтения, некоторые из них являются общими, а некоторые из них выделяются, но никогда не затрагиваются (например, почти все 4GB кучи в этом примере). Но операционная система достаточно умна, чтобы загружать только то, что ей нужно, поэтому размер виртуальной памяти в значительной степени не имеет значения.

где важен размер виртуальной памяти, это если вы работаете в 32-разрядной операционной системе, где вы можете выделить только 2 ГБ (или, в некоторых случаях, 3 ГБ) адресного пространства процесса. В таком случае вы имеете дело с редким и, возможно, придется пойти на компромисс, например, уменьшить размер кучи, чтобы отобразить в памяти большой файл или создать много потоков.

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

размер резидентного набора - это та часть пространства виртуальной памяти, которая фактически находится в ОЗУ. Если ваш RSS растет, чтобы быть значительным часть вашей общей физической памяти, это может быть время, чтобы начать беспокоиться. Если RSS занимает всю вашу физическую память, а система начинает меняться местами, давно пора начать беспокоиться.

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

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

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

доступ к диску (т. е. базе данных) стоит дорого, а память дешевая. Если вы можете обменять одно на другое, сделайте это.

существует известная проблема с Java и glibc >= 2.10 (включая Ubuntu >= 10.04, RHEL >= 6).

лекарство это ОКР. переменная: export MALLOC_ARENA_MAX=4 Если вы используете Tomcat, вы можете добавить это .

резидентной памяти был известен ползучести аналогично утечка памяти или фрагментация памяти.

поиск MALLOC_ARENA_MAX на Гугле или более ссылок.

вы можете настроить и другие параметры malloc для оптимизации низкой фрагментации выделенной памяти:

объем памяти, выделенный для процесса Java, в значительной степени соответствует тому, что я ожидал бы. У меня были аналогичные проблемы с запуском Java на встроенных/ограниченных системах памяти. Бег!--1 - >любой приложение с произвольными ограничениями VM или на системах, которые не имеют достаточного количества свопа, как правило, ломаются. Похоже, это характер многих современных приложений, которые не предназначены для использования в системах с ограниченными ресурсами.

У вас есть несколько вариантов вы можете попробовать и ограничить След памяти JVM. Это может уменьшить объем виртуальной памяти:

- XX: ReservedCodeCacheSize=32M размер кэша зарезервированного кода (в байтах) - максимум размер кэша кода. [Solaris 64-разрядная версия, amd64, и-сервер x86: 48m; в 1.5.0_06 и более ранних версий, Solaris 64-бит и and64: 1024m.]

- XX: MaxPermSize=64m размер постоянного поколения. [5.0 и новее: 64-битные VMs масштабируются на 30% больше; 1.4 для amd64: 96М; 1.3.1 -клиент: 32m.]

кроме того, вы также должны установить-Xmx (максимальный размер кучи) как можно ближе к фактическое пиковое использование памяти приложения. Я считаю, что поведение по умолчанию JVM по-прежнему двойной размер кучи каждый раз, когда он расширяет его до максимального. Если вы начнете с кучи 32M и ваше приложение достигнет пика 65M, то куча будет расти 32M - > 64M- > 128M.

вы также можете попробовать это сделать ВМ менее агрессивно о росте кучи:

- XX: MinHeapFreeRatio=40 минимальный процент кучи свободной после GC к избегайте расширения.

кроме того, из того, что я помню из экспериментов с этим несколько лет назад, количество загруженных собственных библиотек оказало огромное влияние на минимальный след. Загрузка java.сеть.Сокет добавил более 15M, если я правильно помню (и я, вероятно, не).

Sun JVM требует много памяти для HotSpot, и она сопоставляется в библиотеках времени выполнения в общей памяти.

Если проблема с памятью, рассмотрите возможность использования другой JVM, подходящей для встраивания. IBM имеет j9, и есть открытый исходный код "jamvm", который использует библиотеки GNU classpath. Также У Sun есть писк JVM, работающий на солнечных пятнах, поэтому есть альтернативы.

просто мысль, но вы можете проверить влияние a ulimit -v опции.

это не фактическое решение, так как оно ограничит адресное пространство, доступное для все процесс, но это позволит вам проверить поведение вашего приложения с ограниченной виртуальной памятью.

одним из способов уменьшения кучи системы с ограниченными ресурсами может быть игра с переменной-XX: MaxHeapFreeRatio. Это обычно устанавливается в 70 и является максимальным процентом кучи, которая свободна до того, как GC сжимает ее. Установив его на более низкое значение, вы увидите, например, в профилировщике jvisualvm, что для вашей программы обычно используется меньшая куча.

EDIT: чтобы установить небольшие значения для-XX: MaxHeapFreeRatio, вы также должны установить-XX:MinHeapFreeRatio Например

EDIT2: добавлен пример для реального приложения, которое запускается и выполняет ту же задачу, один с параметрами по умолчанию и один с 10 и 25 в качестве параметров. Я не заметил никакой реальной разницы в скорости, хотя Java теоретически должна использовать больше времени для увеличения кучи в последнем примере.

Default parameters

в конце, максимальная куча 905, используемая куча 378

MinHeap 10, MaxHeap 25

в конце, максимальная куча 722, используемая куча 378

это на самом деле имеет некоторые inpact, как наше приложение работает на сервере удаленного рабочего стола, и многие пользователи могут запустить его сразу.

java 1.4 Sun имеет следующие аргументы для управления размером памяти:

-Xmsn Укажите начальный размер пула распределения памяти в байтах. Это значение должно быть кратно 1024 больше чем 1МБ. Добавить букву k или K, чтобы указать килобайты, или m или M для обозначения мегабайт. Неисполнение значения 2Мб. Примеры:

- Xmxn Укажите максимальный размер пула распределения памяти в байтах. Это значение должно быть кратно 1024 больше чем 2Мб. Добавить букву k или K, чтобы указать килобайты, или m или M для обозначения мегабайт. Неисполнение значение 64Мб. Примеры:

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

Alernatively, вы можете попробовать другую JVM, а затем Sun one, с меньшим объемом памяти, но я не могу посоветовать здесь.

Читайте также: