Использование виртуальной памяти из Java под Linux, используется слишком много памяти

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

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

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

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

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

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

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


person Mario Ortegón    schedule 18.02.2009    source источник
comment
Почему вас беспокоит использование виртуальной памяти? Если вам действительно интересно, посмотрите на использование резидентной памяти и прочтите следующие команды: free, ps, top.   -  person basszero    schedule 18.02.2009
comment
В системе работает еще несколько приложений, которые встроены. И у системы есть ограничение виртуальной памяти.   -  person Mario Ortegón    schedule 18.02.2009
comment
аааа, дьявол кроется в деталях   -  person basszero    schedule 18.02.2009
comment
Какую реализацию Java вы используете. IIRC, бесплатная Sun JRE (не OpenJDK), не лицензированная для встроенного использования.   -  person Tom Hawtin - tackline    schedule 18.02.2009
comment
Я думаю, что я не использовал встроенную часть ... это ограниченная память и оборудование настроено, но это все еще стандартный компьютер   -  person Mario Ortegón    schedule 20.02.2009
comment
Для ограниченных / встроенных систем я обнаружил, что могу сэкономить немного памяти, настроив переменную -XX: MaxHeapFreeRatio, подробности см. В моем ответе ниже.   -  person runholen    schedule 21.01.2015
comment
@ MarioOrtegón Если это стандартный компьютер, то есть на нем действительно может работать официальная версия Oracle JDK / OpenJDK, на самом деле не должно быть никаких необычных ограничений виртуальной памяти. Доступное адресное пространство (виртуальная память) встроено в ЦП и управляется операционной системой. Виртуальная память одного процесса не мешает другому процессу. Другое дело, конечно, физическая память.   -  person nos    schedule 21.04.2015


Ответы (8)


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

java -Xms1024m -Xmx4096m com.example.Hello

Различные способы измерения памяти

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

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 2120 kgregory  20   0 4373m  15m 7152 S    0  0.2   0:00.10 java
  • VIRT - это пространство виртуальной памяти: сумма всего на карте виртуальной памяти (см. Ниже). Это в значительной степени бессмысленно, за исключением тех случаев, когда это не так (см. Ниже).
  • RES - это размер резидентного набора: количество страниц, которые в настоящее время находятся в ОЗУ. Почти во всех случаях это единственное число, которое следует использовать, когда вы говорите «слишком большой». Но это все равно не очень хорошая цифра, особенно если говорить о Java.
  • SHR - это объем резидентной памяти, которая используется совместно с другими процессами. Для процесса Java это обычно ограничивается разделяемыми библиотеками и JAR-файлами с отображением в память. В этом примере у меня был запущен только один процесс Java, поэтому я подозреваю, что 7k является результатом использования библиотек в ОС.
  • SWAP не включен по умолчанию и здесь не отображается. Он указывает объем виртуальной памяти, которая в настоящее время находится на диске, действительно ли она находится в пространстве подкачки. ОС очень хорошо хранит активные страницы в ОЗУ, и единственное средство от подкачки - (1) купить больше памяти или (2) уменьшить количество процессов, поэтому лучше не обращать внимания на это число.

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

Понимание карты виртуальной памяти

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

0000000040000000     36K r-x--  /usr/local/java/jdk-1.6-x64/bin/java
0000000040108000      8K rwx--  /usr/local/java/jdk-1.6-x64/bin/java
0000000040eba000    676K rwx--    [ anon ]
00000006fae00000  21248K rwx--    [ anon ]
00000006fc2c0000  62720K rwx--    [ anon ]
0000000700000000 699072K rwx--    [ anon ]
000000072aab0000 2097152K rwx--    [ anon ]
00000007aaab0000 349504K rwx--    [ anon ]
00000007c0000000 1048576K rwx--    [ anon ]
...
00007fa1ed00d000   1652K r-xs-  /usr/local/java/jdk-1.6-x64/jre/lib/rt.jar
...
00007fa1ed1d3000   1024K rwx--    [ anon ]
00007fa1ed2d3000      4K -----    [ anon ]
00007fa1ed2d4000   1024K rwx--    [ anon ]
00007fa1ed3d4000      4K -----    [ anon ]
...
00007fa1f20d3000    164K r-x--  /usr/local/java/jdk-1.6-x64/jre/lib/amd64/libjava.so
00007fa1f20fc000   1020K -----  /usr/local/java/jdk-1.6-x64/jre/lib/amd64/libjava.so
00007fa1f21fb000     28K rwx--  /usr/local/java/jdk-1.6-x64/jre/lib/amd64/libjava.so
...
00007fa1f34aa000   1576K r-x--  /lib/x86_64-linux-gnu/libc-2.13.so
00007fa1f3634000   2044K -----  /lib/x86_64-linux-gnu/libc-2.13.so
00007fa1f3833000     16K r-x--  /lib/x86_64-linux-gnu/libc-2.13.so
00007fa1f3837000      4K rwx--  /lib/x86_64-linux-gnu/libc-2.13.so
...

Краткое объяснение формата: каждая строка начинается с адреса виртуальной памяти сегмента. Далее следует размер сегмента, разрешения и источник сегмента. Этот последний элемент является либо файлом, либо "аноном", который указывает блок памяти, выделенный с помощью 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 гораздо важнее обращать внимание на то, что происходит в куче. Общий объем занимаемого пространства важен, и вы можете предпринять некоторые шаги, чтобы его уменьшить. Более важным является количество времени, которое вы тратите на сборку мусора, и какие части кучи собираются.

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

person kdgregory    schedule 18.02.2009
comment
Вы должны принять во внимание, что части памяти, которые в настоящее время выгружены, отсутствуют в измерении RES. Таким образом, у вас может быть низкое значение RES, но только потому, что приложение было неактивным и большая часть кучи была выгружена на диск. Java очень плохо справляется с подкачкой: на каждом полном сборщике мусора большая часть кучи проходит и копируется, поэтому, если большая часть вашей кучи была в подкачке, сборщик мусора должен загрузить все это обратно в основную память. - person jrudolph; 20.05.2010
comment
Отличный ответ, kdgregory! Я работаю во встроенной среде, используя CF, в котором НЕТ места для подкачки. Итак, основываясь на вашем ответе, все мои значения VIRT, SWAP и nFLT взяты из файлов с отображением памяти ... что теперь имеет смысл для меня. Знаете ли вы, представляет ли значение SWAP страницы, которые еще не были загружены в память, или страницы, которые были выгружены из памяти, или и то, и другое? Как мы можем получить представление о возможном сбивании (непрерывная карта, а затем замена)? - person Jeach; 21.09.2010
comment
@Jeach - я был удивлен тем, что сообщалось о каком-либо свопинге, поэтому загрузил свой путешествующий Linux (флэш-накопитель с Ubuntu 10.04 и без свопа). Когда я включил столбец SWAP в top, я увидел, что Eclipse имеет 509 метров. Когда я затем посмотрел на него с помощью pmap, общее виртуальное пространство составило 650 м. Поэтому я подозреваю, что цифра SWAP представляет все страницы на диске, а не только те, которых нет в памяти. - person kdgregory; 26.09.2010
comment
Что касается вашего второго вопроса: если вы постоянно читаете страницы с флэш-карты, ваше время ожидания ввода-вывода (показанное в сводке top как% wa) должно быть большим. Однако помните, что это будет высоким значением для любой активности, особенно для записи (при условии, что ваша программа выполняет какие-либо действия). - person kdgregory; 26.09.2010
comment
HelloWorld в моей системе всегда показывает анонимные блоки размером 28 * 65 МБ в pmap, это 1,8 ГБ VIRT! Я предполагаю, что теперь это сопоставленные файлы, и не о чем беспокоиться ... благодаря @kdgregory. Но кто-нибудь знает, что это такое? Учитывая, что все они находятся на границе ByteBuffer Integer.MAX_VALUE размером 65 МБ, это может быть один огромный файл? Это все классы JVM и собственные библиотеки? / proc / * / fd, похоже, не показывает ничего, кроме jre / lib / rt.jar, который даже близко не стоит. Возможно, зависит от JVM / OS, но хотелось бы узнать больше! - person Josh; 26.07.2013
comment
@Josh - pmap сообщит вам имя сопоставленного файла. Анонимные блоки используются для других распределений: стеки потоков, куча Java и данные, выделяемые собственными библиотеками. Я бы счел Hello World, который занимает 1,8 Гб, очень необычным. - person kdgregory; 29.07.2013
comment
Может ли вывод pmap быть полезным для понимания проблем с памятью при использовании вне кучи? - person haridsv; 07.11.2014
comment
@haridsv - на очень грубом уровне, да. Если у вас есть код JNI, который выполняет распределение, и вы понимаете, как malloc реализован для вашей платформы, вы можете определить ситуацию, в которой происходит утечка памяти. Однако я думаю, что для этого есть инструменты получше (например, valgrind). - person kdgregory; 08.11.2014
comment
Это лучший ответ. Могу я задать еще один вопрос? Я установил -Xmx5000m -Xms5000m, но я видел, что мое приложение VIRT составляет 8875 м, RES - 2,2 г, как это происходит? - person Xilang; 29.07.2016
comment
›Блок 1M представляет собой стек потоков; Я не знаю, что входит в блок 4K. Блок 4K, который отмечен как не имеющий разрешений на чтение и запись, скорее всего, является защитным блоком. При переполнении стека осуществляется доступ к этой области, что вызывает сбой, который JVM может обработать, создав исключение Java StackOverflowException. Это намного дешевле, чем проверять указатель стека при каждом вызове метода. Защитные области без установленных разрешений также могут использоваться в других контекстах. - person eriksoe; 20.04.2020
comment
@eriksoe - в этом есть смысл, я отредактирую ответ. - person kdgregory; 25.04.2020
comment
Отличный ответ !! Если вы не меняете местами, не беспокойтесь о том, что вам говорят различные статистические данные о памяти. но мне было интересно, что вызовет своп, должен ли я уделять внимание RSS ??? - person Scott 混合理论; 29.09.2020

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

Лекарство - установить этот env. Переменная:

export MALLOC_ARENA_MAX=4

Если вы используете Tomcat, вы можете добавить это в TOMCAT_HOME/bin/setenv.sh файл.

Для Docker добавьте это в Dockerfile

ENV MALLOC_ARENA_MAX=4

Существует статья IBM о настройке MALLOC_ARENA_MAX .ibm.com / developerworks / community / blogs / kevgrig / entry / linux_glibcTOMCAT_HOME/bin/setenv.sh10_rhel_6_malloc_may_show_excessive_virtual_memory_usage? lang = en

В этом сообщении блога говорится, что

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

Также существует открытая ошибка JDK JDK-8193521 "glibc тратит память при конфигурации по умолчанию"

найдите MALLOC_ARENA_MAX в Google или SO для получения дополнительных ссылок.

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

# tune glibc memory allocation, optimize for low fragmentation
# limit the number of arenas
export MALLOC_ARENA_MAX=2
# disable dynamic mmap threshold, see M_MMAP_THRESHOLD in "man mallopt"
export MALLOC_MMAP_THRESHOLD_=131072
export MALLOC_TRIM_THRESHOLD_=131072
export MALLOC_TOP_PAD_=131072
export MALLOC_MMAP_MAX_=65536
person Lari Hotari    schedule 09.03.2015
comment
Этот ответ действительно помог мне на 64-битном сервере Ubuntu с сервером TomEE, который мало потреблял память. Ссылка на статью IBM действительно является глубоким объяснением. Еще раз спасибо за этот хороший совет! - person MWiesner; 20.06.2015
comment
В JVM может происходить утечка собственной памяти, что приводит к аналогичным симптомам. См. stackoverflow.com/a/35610063/166062. Незакрытые экземпляры GZIPInputStream и GZIPOutputStream также могут быть источником утечки. - person Lari Hotari; 16.09.2016
comment
В Java 8 есть ошибка JVM, которая приводит к неограниченному росту собственной памяти: bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8164293. Если вас это беспокоит, использование MALLOC_ARENA_MAX может замедлить рост вашей памяти, но не решить проблему полностью. - person outofcoffee; 20.01.2017
comment
@LariHotari очень признателен за ваши усилия по указанию версий glibc и redhat - person Sam; 06.05.2017
comment
Java 8u131 содержит исправление для связанной ошибки JVM JDK-8164293 bugs.openjdk.java.net / browse / JDK-8178124. - person Lari Hotari; 31.05.2017
comment
Также имеются связанные отчеты об ошибках bugs.openjdk.java.net/browse/JDK-8193521 и bugzilla.redhat.com/show_bug.cgi?id=1527196 - person Lari Hotari; 15.02.2019

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

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

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

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

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

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

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

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

person James Schek    schedule 18.02.2009

Sun JVM требует много памяти для HotSpot и отображает библиотеки времени выполнения в разделяемой памяти.

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

person Thorbjørn Ravn Andersen    schedule 03.03.2009
comment
Есть ли возможность отключить горячую точку? - person Mario Ortegón; 04.03.2009
comment
Возможно. Проверьте параметры командной строки для используемой JVM. - person Thorbjørn Ravn Andersen; 04.03.2009

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

РЕДАКТИРОВАТЬ: Чтобы установить небольшие значения для -XX: MaxHeapFreeRatio, вы также должны установить -XX: MinHeapFreeRatio Eg

java -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=25 HelloWorld

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

Параметры по умолчанию

В итоге максимальная куча составляет 905, используемая куча - 378

MinHeap 10, MaxHeap 25

В итоге максимальная куча - 722, используемая куча - 378

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

person runholen    schedule 16.01.2015

Просто подумайте, но вы можете проверить влияние вариант ulimit -v.

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

person VonC    schedule 18.02.2009
comment
В этом и заключается моя проблема. Моя куча установлена ​​на 64 МБ, но Linux резервирует 204 МБ. Если я установлю ulimit ниже 204, приложение вообще не запустится. - person Mario Ortegón; 18.02.2009
comment
Интересно: установка ulimit может иметь непреднамеренный побочный эффект для других процессов, объясняющий, почему приложение не может работать. - person VonC; 18.02.2009
comment
Проблема, похоже, в том, что Java требует зарезервировать этот больший объем виртуальной памяти, даже если она не будет ее использовать. В Windows используемая виртуальная память и настройка Xmx более близки. - person Mario Ortegón; 18.02.2009
comment
Вы пробовали это с JRockit JVM? - person VonC; 18.02.2009
comment
Поскольку выделение памяти JVM представляет собой сумму распределения кучи и размера Perm (первый можно исправить с помощью параметров -Xms и -Xmx), пробовали ли вы некоторые настройки с помощью -XX: PermSize и -XX: MaxPermSize (по умолчанию от 32 МБ до 64 МБ в зависимости от версии JVM)? - person VonC; 18.02.2009
comment
К сожалению, я не могу изменить JVM, так как это встроенная система, а виртуальная машина используется для некоторых других опций. - person Mario Ortegón; 18.02.2009

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

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

           -Xms6291456
           -Xms6144k
           -Xms6m

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

           -Xmx83886080
           -Xmx81920k
           -Xmx80m

http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/java.html

В Java 5 и 6 есть еще кое-что. См. http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp

person Paul Tomblin    schedule 18.02.2009
comment
У меня проблема не в размере кучи, а в объеме виртуальной памяти, назначенной Linux. - person Mario Ortegón; 18.02.2009
comment
Прочтите объяснение kdgregory. Уменьшение размера кучи, нового размера и других настраиваемых параметров уменьшит объем РЕАЛЬНОЙ памяти, которую занимает jvm. - person Paul Tomblin; 18.02.2009
comment
У него может быть законная проблема. Некоторые приложения (например, одно, которое я написал) отображают файл размером 1 ГБ, а некоторые системы имеют только 2 ГБ виртуальной памяти, некоторые из которых заполняются разделяемыми библиотеками. И если это проблема, ему обязательно следует отключить рандомизацию DSO. В / proc есть опция. - person Zan Lynx; 11.06.2010

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

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

person Marko    schedule 18.02.2009