2013-03-07 3 views
16

У меня есть проект, который я пишу (на Java) для класса, где профессор говорит, что нам не разрешено использовать более 200 м. . Я ограничиваю память стека 50 (только, чтобы быть абсолютно уверены) с -Xmx50m, но в соответствии с верхней, она по-прежнему с использованием 300мJava использует гораздо больше памяти, чем выделено с -Xmx

Я попытался запустить Eclipse Memory Analyzer и сообщает только 26м

Может ли это все быть память на стеке ?, Я довольно уверен, что я никогда не пойду дальше, чем около 300 вызовов методов в глубину (да, это рекурсивный поиск DFS), так что это должно означать, что каждый стек стека использует почти мегабайт, который, кажется, трудно поверить.

Программа однопоточная. Кто-нибудь знает какие-либо другие места, в которых я мог бы уменьшить использование памяти? Кроме того, как я могу проверить/ограничить, сколько памяти использует стек?

UPDATE: Я использую следующие параметры виртуальной машины Java теперь без эффекта (еще около 300 м в зависимости от топ): -Xss104k -Xms40m -Xmx40m -XX:MaxPermSize=1k

другого UPDATE: На самом деле, если я смочите немного больше (со всеми этими варианты) примерно в половине случаев, когда он внезапно падает до 150 м через 4 или 5 секунд (другая половина не падает). Что делает это действительно странным, так это то, что моя программа не имеет стохастичности (и, как я уже сказал, это однопоточный), поэтому нет причин, по которым она должна вести себя по-разному на разных трассах.

Может ли это иметь какое-то отношение к JVM, который я использую ?

java version "1.6.0_27" 
OpenJDK Runtime Environment (IcedTea6 1.12.3) (6b27-1.12.3-0ubuntu1~10.04) 
OpenJDK 64-Bit Server VM (build 20.0-b12, mixed mode) 

Согласно java -h, JVM по умолчанию - это -сервер. Я попробовал добавить -cacao и теперь (со всеми другими вариантами), это всего 59 м. Поэтому я полагаю, что это решает мою проблему. Может ли кто-нибудь объяснить, почему это было необходимо? Кроме того, есть ли какие-то недостатки, о которых я должен знать?

Еще одно обновление: какао действительно очень медленное по сравнению с сервером. Это ужасный вариант

+0

Память кучи и память стека настраиваются отдельно. Память, которую вы видите в верхней части, включает и то, и другое. – dnault

+0

Я понимаю это, но я не думаю, что это стек памяти. Я не так много использую. Итак, где еще может быть память с – dspyz

+0

Вы также устанавливаете минимальный размер кучи? Если '-Xms' больше, чем' -Xmx', я думаю, что он использует до -Xms' –

ответ

4

С -Xmx вы настраиваете размер кучи. Чтобы настроить размер стека, используйте параметр -Xss. Сумма этих двух параметров должна быть примерно того, что вы хотите:

-Xmx150m -Xss50m 

например.

Дополнительно есть также -XX:MaxPermSize Параметр, который контролирует. Этот параметр для -client имеет значение по умолчанию 32 МБ и для -server 64 МБ. В соответствии с вашей конфигурацией вычислите его также. Пространство PermGen:

Постоянное поколение используется для отображения отражающей самой ВМ, такой как объекты класса и объекты метода.

Таким образом, в основном он хранит внутренние данные JVM, такие как определения классов и встроенные строки.

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

+0

Не забывайте пространство PermGen – danpaq

+0

Спасибо, я только что нашел и попробовал это. Это не имело значения. Я не использую память стека. Где еще это могло произойти, если это не куча или стек? – dspyz

+0

Что такое пространство PermGen и как его ограничить? – dspyz

10

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

  • Основной накладные расходы памяти самой виртуальной машины Java
  • кучи пространства, ограниченного (с -Xmx)
  • ПОСТОЯННОГО поколения пространства (-XX: MaxPermSize - не стандартный во всех виртуальных машинах)
  • нитей укладывают пространство (-Xss в стек), который может значительно возрасти в зависимости от числа потоков
  • пространства, используемых носителей распределений (с использованием класса ByteBufer или JNI)
+0

Нет байтовых буферов (если только в них не используется структура коллекций), ограничение PermGen, похоже, ничего не меняет. Я называю System.arraycopy, который, я считаю, использует JNI, верно? Может ли это так? – dspyz

+0

@dspyz: Я не думаю, что arrayCopy использует дополнительное пространство вне пространства кучи. Он копирует данные из одного места кучи в другое. Я бы пересмотрел количество потоков, созданных вашим приложением. –

+0

Нет, однопоточный. Все, что я вижу (в отладчике eclipse), это Main thread, Signal Dispatcher, Finalizer и Reference Handler – dspyz

1

Вы пытались использовать JVisualVM?

http://docs.oracle.com/javase/6/docs/technotes/tools/share/jvisualvm.html

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

+0

Кажется, что нет версии для Linux – dspyz

+2

Он должен быть в каталоге bin JDK (а не JRE); который не может быть на вашем PATH. – danpaq

1

Важно отметить, что «общая память используется» (RSS на земле Linux) включает кучу JDK (+ другие области JDK), а также выделенную «родную память».

Например, эти люди обнаружили, что выделение слишком большого количества jaxbcontexts (которые связаны с родной памятью) между GC может привести к использованию большого количества дополнительной ОЗУ. Другим распространенным является, по-видимому ZipInflater, если вы не вызываете близко от него (или GZipStream и т.д.)

http://sleeplessinslc.blogspot.com/2014/08/jvm-native-memory-leak.html

Его последний обходной путь/исправление было либо GC «чаще» (с помощью GC1 сборщика мусора , или указывая меньше [по иронии судьбы] -Xmx) или путем кэширования объектов JaxBContext (так как они не имеют близкого метода, поэтому вы не можете контролировать утечку).

отметить также, что иногда вы можете найти виноватых памяти, только исследуются jstack: http://javaeesupportpatterns.blogspot.com/2011/09/jaxbcontext-performance-problem-case.html

Также иногда можно «пропустить» закрытие, например GZipStreams случайно http://kohsuke.org/2011/11/03/quiz-time-memory-leak-in-java

3
Max memory = [-Xmx] + [-XX:MaxPermSize] + number_of_threads * [-Xss] 

здесь макс памяти кучи, как - Xmx, минимальная память кучи как -Xms, стек памяти как -Xss и -XX maxPermSize

Следующий пример иллюстрирует эту ситуацию. Я запустил свой tomcat со следующими параметрами запуска:

-Xmx168m -Xms168m -XX:PermSize=32m -XX:MaxPermSize=32m -Xss1m 
Смежные вопросы