2015-01-30 4 views
2

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

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

Когда я запускаю программу, она всегда останавливается после создания 218 или 219 и выдает «OutOfMemoryError». Как только он говорит Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded и один раз Exception in thread "main" java.lang.OutOfMemoryError: Java heap space.

Я полагаю, что программа создает слишком много объектов с течением времени, пока не закончится память при вычислении 218-го или 219-го ввода. Каждый экземпляр вычисляется в независимом режиме. Следовательно, он должен решить проблему, чтобы очистить память и избавиться от всех созданных объектов после того, как результат будет сохранен и до того, как будет обработан следующий вход. Это верно? Я слышал, что использование System.gc() - это плохая практика, но что еще вы бы порекомендовали в моем случае?

Edit: Чтобы указать, что я хочу: Вместо того, чтобы нажать «Пуск» для каждого входа, я осуществил цикл, чтобы сделать это для меня. Тем не менее, похоже, что он не ведет себя одинаково и сохраняет старые объекты из предыдущих прогонов. Могу ли я изменить код Java таким образом, что он ведет себя аналогично запуску программы заново для каждого входа? Или мне нужно использовать оболочку skript, которая запускает мою эвристику для каждого входа отдельно, чтобы заставить ее работать? Я никогда не использовал параметры JVM, и мне кажется, что они не справляются с этой проблемой.

Решено: Фактически была обнаружена и исправлена ​​утечка памяти. Нет System.gc(). Спасибо за помощь в любом случае!

+1

Вы можете поймать 'OutOfMemoryError', но вы не должны (вы ничего не можете с этим поделать). У вас есть два варианта: Запустите Java с дополнительным пространством кучи '-Xmx2048m' или отлаживайте свой код, чтобы не оставлять столько кусков в куче. Устанавливайте неиспользуемые объекты на «null» после того, как вы закончите с ними. И да, не называйте 'System.gc()', это вам не поможет. – Kon

+0

Дополнительное место кучи не поможет, если объекты с предыдущих входов остаются в куче. Это приведет к задержке OutOfMemoryError. И установка всех объектов, которые мне больше не нужны, «null» кажется странным и требует больших усилий. Было бы лучше очистить все после каждого прогона. – CGFoX

+0

Как только JVM запустил и выполнил какое-то нетривиальное количество работы, нет способа вернуть его к «первозданному» состоянию. Но если вы утверждаете, что каждая итерация вашего кода является «независимой», но вы все еще получаете OOM, ваше требование независимости является ложным, и вы как-то навязываете результаты между итерациями. –

ответ

0

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

  • Увеличьте размер кучи с помощью XMX ...
  • параметр
  • Set надлежащего алгоритма и параметров ГХ. Если у вас есть уже есть параметры GC пытаются настроить parameters
  • Попробуйте использовать -XX: + HeapDumpOnOutOfMemoryError и -XX: HeapDumpPath = < путь для дампа кучи> опции при запуске виртуальной машины Java, так что вы получите дамп кучи, когда ваш работает JVM ООМ. Используя дамп кучи, вы можете использовать профайлеры, такие как jprofiler/yourkit/jvisualvm и т. Д., Чтобы исследовать утечки памяти, а затем исправить то же самое.
0

Первый, при запуске виртуальной машины Java для запуска ваших тестов, отключить ограничение GC накладные:

-XX:-UseGCOverheadLimit 

Я рекомендую это потому, что вы уже знаете, что вы намеренно подчеркивая сборщик мусора, и вы не хотите, чтобы он предупреждал вас о сбоях в работе GC.

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

Третий, если вам все еще нужно больше памяти, из-за превышения Java heap space, используйте:

-Xms<size>  set initial Java heap size 
-Xmx<size>  set maximum Java heap size 

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

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

Четвертый, другая настройка виртуальной машины Java, которые могут быть полезны в ваших обстоятельствах:

-XX:NewRatio=<n> Ratio of old/new generation sizes. The default value is 2. 

Это обычно не рекомендуется устанавливать ниже 2 (2/3 старого, 1/3 нового), но в в вашей ситуации я мог бы предложить вам попробовать установить это на 1 (1/2 старый, 1/2 новый).

См. Также GC overhead limit exceeded и выезд Java HotSpot VM Options.

0

Дайте это попробовать: http://javaandroidandrest.blogspot.de/2012/06/wait-for-jvm-garbage-collector.html

С сайта:

Использование таких функций, как System.gc(); или Runtime.getRuntime(). gc(); только предлагайте JVM, что вы хотите запустить сборщик мусора. Я нашел способ в Интернете не заставлять сборщика коллекций, а ждать, пока не появится сборщик мусора.

Смежные вопросы