Работа с ошибкой «java.lang.OutOfMemoryError: PermGen space»


1223

Недавно я столкнулся с этой ошибкой в ​​моем веб-приложении:

java.lang.OutOfMemoryError: пространство PermGen

Это типичное приложение Hibernate / JPA + IceFaces / JSF, работающее на Tomcat 6 и JDK 1.6. По-видимому, это может произойти после повторного развертывания приложения несколько раз.

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


Я боролся с этим часами, но у меня нет хороших новостей. См. Мой связанный вопрос: stackoverflow.com/questions/1996088/… У вас все еще может быть утечка памяти, например, классы не являются сборщиком мусора, потому что ваш WebAppClassLoader не сборщик мусора (он имеет внешнюю ссылку, которая не очищается). увеличение PermGen только задержит OutOfMemoryError, и разрешение сбора мусора классов является предварительным условием, но не будет собирать классы мусора, если их загрузчик классов все еще имеет ссылки на него.
Эран Медан

Я получил эту ошибку при добавлении отображения taglib . Удаление так и решило ошибку. Почему так?
МАСТ

И как ты столкнулся с этим?
Турбьёрн Равн Андерсен

13
используйте JDK 1.8: þ добро пожаловать в MetaSpace
Rytek

Если вы используете Windows, следуйте этим инструкциям, а не пытаться установить флаги вручную в файлах конфигурации. Это правильно устанавливает значения в реестре, которые будут вызываться Tomcat во время выполнения. stackoverflow.com/questions/21104340/…
MacGyver

Ответы:


563

Решением было добавить эти флаги в командную строку JVM при запуске Tomcat:

-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled

Это можно сделать, выключив службу tomcat, затем перейдя в каталог Tomcat / bin и запустив tomcat6w.exe. На вкладке «Java» добавьте аргументы в поле «Параметры Java». Нажмите «ОК» и перезапустите сервис.

Если вы получили сообщение об ошибке, указанная служба не существует как установленная служба, вы должны запустить:

tomcat6w //ES//servicename

где servicename - это имя сервера в соответствии с services.msc

Источник: комментарий orx к Agile Ответам Эрика .


39
В статье ниже предлагается -XX: + UseConcMarkSweepGC и -XX: MaxPermSize = 128m. my.opera.com/karmazilla/blog/2007/03/13/…
Тейлор Лиз

30
-XX: + CMSPermGenSweepingEnabled Этот параметр снижает производительность. Это заставляет каждый запрос занимать в три раза больше времени, чем обычно в наших системах. Используйте с осторожностью.
Eldelshell

10
работал для меня - спасибо - я делаю это на Ubuntu 10.10 с Tomcat6 - я создал новый файл: /usr/share/tomcat6/bin/setenv.sh и добавил к этому следующую строку: JAVA_OPTS = "- Xms256m -Xmx512m - XX: + CMSClassUnloadingEnabled -XX: + CMSPermGenSweepingEnabled "- Перезапущенный кот с помощью: sudo /etc/init.d/tomcat6 start
sam

24
При запуске tomcat 6.0.29 из моего лог-файла catalina.out: «В будущем используйте CMSClassUnloadingEnabled вместо CMSPermGenSweepingEnabled»
knb

222
Прежде всего было бы здорово объяснить, что на самом деле делают эти флаги. Просто сказать: «делай и наслаждайся» ИМХО не достаточно.
Nikem

251

Лучше попробуй -XX:MaxPermSize=128M, чем -XX:MaxPermGen=128M.

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


9
На самом деле, это только отложит OOMError. Смотрите ответ ниже, начатый anon с двумя ссылками на блог frankkieviet.
Rade_303

Эти варианты описаны здесь: oracle.com/technetwork/java/javase/tech/...
амосс

153

Ошибки PermGen сервера приложений, возникающие после нескольких развертываний, вероятнее всего вызваны ссылками, содержащимися в контейнере на загрузчики классов ваших старых приложений. Например, использование пользовательского класса уровня журнала приведет к тому, что ссылки будут храниться загрузчиком классов сервера приложений. Вы можете обнаружить эти утечки между классами загрузчика, используя современные (JDK6 +) инструменты анализа JVM, такие как jmap и jhat, чтобы посмотреть, какие классы по-прежнему хранятся в вашем приложении, и изменить или исключить их использование. Обычно подозреваемыми являются базы данных, средства ведения журнала и другие библиотеки базового уровня.

См. Утечки Classloader: страшное исключение "java.lang.OutOfMemoryError: PermGen space" , и особенно его последующий пост .


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

Другой очень хороший источник - people.apache.org/~markt/presentations/… (от менеджера релизов Tomcat !!).
gavenkoa

22
Хотя это может теоретически ответить на вопрос, было бы предпочтительным включить сюда основные части ответа и предоставить ссылку для справки.
Йоахим Зауэр

68

Распространенные ошибки, которые делают люди, - это думать, что куча пространства и пространство permgen одно и то же, что вовсе не так. У вас может быть много свободного места в куче, но все равно может не хватить памяти в permgen.

Распространенными причинами OutofMemory в PermGen является ClassLoader. Всякий раз, когда класс загружается в JVM, все его метаданные вместе с Classloader хранятся в области PermGen, и они будут собираться мусором, когда загрузчик Classloader, который их загрузил, готов для сбора мусора. В случае, если Classloader имеет утечку памяти, все загруженные им классы останутся в памяти и вызовут излишнюю память permGen, если вы повторите это пару раз. Классическим примером является Java.lang.OutOfMemoryError: PermGen Space в Tomcat .

Теперь есть два способа решить эту проблему:
1. Найти причину утечки памяти или, если есть утечка памяти.
2. Увеличьте размер пространства PermGen с помощью параметра JVM -XX:MaxPermSizeи -XX:PermSize.

Вы также можете проверить 2 Решение Java.lang.OutOfMemoryError в Java для более подробной информации.


3
Как передать параметр -XX:MaxPermSize and -XX:PermSize?? Я не могу найти catalina.bat. Моя версия кота есть 5.5.26.
Deckard

Как найти утечки памяти в загрузчике классов? Вы рекомендуете какой-либо инструмент?
Амит

@amit для получения рекомендаций по инструментам, см. вики-ответ сообщества на этот вопрос.
Баретт

@Deckard заходит в каталог Tomcat / bin и запускает tomcat6w.exe. На вкладке «Java» добавьте аргументы в поле «Параметры Java». Нажмите «ОК»
Зеб

43

Используйте параметр командной строки -XX:MaxPermSize=128mдля Sun JVM (очевидно, заменив 128 на любой нужный вам размер).


9
Единственная проблема в том, что вы просто откладываете неизбежное - в какой-то момент у вас там тоже будет запас прочности. Это отличное прагматичное решение, но оно не решает его навсегда.
Тим Хоулэнд

То же самое происходит в Eclipse, и каждый раз, когда у вас много динамической загрузки классов. загрузчики классов не утилизируются и живут в вечном поколении вечно
Мэтт

1
У меня заканчивался PermGen, когда я выполнял особенно большую работу в Хадсоне ... это исправило это для меня.
HDave

10
@TimHowland, это может быть постоянное исправление, если основной причиной является не утечка загрузчика классов, а слишком большое количество классов / статических данных в вашем веб-приложении.
Петер Тёрёк

возникла та же проблема, что и у HDave при сборке jenkins / hudson из исходного кода.
Луизгаб

38

Попробуйте, -XX:MaxPermSize=256mи если это не устранено, попробуйте-XX:MaxPermSize=512m


56
и если это все еще будет продолжаться, попробуйте XX:MaxPermSize=1024m:)
igo

38
и если это все еще сохраняется, попробуйте XX: MaxPermSize = 2048m :)
Томас

16
И если это по-прежнему сохраняется, переосмыслить ваше приложение! Или попробуйте XX: MaxPermSize = 4096 м :)
Джонатан Эйри,

17
Вы также можете попробовать 8192 м, но это немного
излишне

12
Избыток действительно - 640KB должно быть достаточно для всех!
Джоэл Пурра

28

Я добавил -XX: MaxPermSize = 128m (вы можете поэкспериментировать, который работает лучше всего) в VM Arguments, так как я использую Eclipse Ide. В большинстве JVM значение PermSize по умолчанию составляет около 64 МБ, что приводит к нехватке памяти, если в проекте слишком много классов или огромное количество строк.

Для затмения это также описано в ответе .

ШАГ 1 : Двойной щелчок по серверу Tomcat на вкладке Servers

введите описание изображения здесь

ШАГ 2 : Open запуск Conf и добавить -XX: MaxPermSize = 128mв конце существующих заданы параметры виртуальной машины .

введите описание изображения здесь


1
Спасибо за ваш лучший подробный ответ (Примечание: нажмите «Открыть конфигурацию запуска», чтобы открыть окно «Редактировать конфигурацию» ... но я использовал следующие параметры: «-XX: + CMSClassUnloadingEnabled -XX: + CMSPermGenSweepingEnabled»
Chris Sim

23

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

Когда я развертываю приложение в Apache Tomcat, для него создается новый ClassLoader. ClassLoader затем используется для загрузки всех классов приложения, а при отмене развертывания все должно пройти хорошо. Однако на самом деле все не так просто.

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

И после нескольких повторных развертываний мы сталкиваемся с ошибкой OutOfMemoryError.

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

Поэтому вместо этого я собрал решение в коде, которое работает на Apache Tomcat 6.0. Я не тестировал ни на каких других серверах приложений и должен подчеркнуть, что, скорее всего, это не сработает без изменений на любом другом сервере приложений .

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

Во всяком случае, с кодом. Это следует вызывать в тот момент, когда приложение развертывается - например, метод уничтожения сервлета или (лучший подход) метод contextDestroyed ServletContextListener.

//Get a list of all classes loaded by the current webapp classloader
WebappClassLoader classLoader = (WebappClassLoader) getClass().getClassLoader();
Field classLoaderClassesField = null;
Class clazz = WebappClassLoader.class;
while (classLoaderClassesField == null && clazz != null) {
    try {
        classLoaderClassesField = clazz.getDeclaredField("classes");
    } catch (Exception exception) {
        //do nothing
    }
    clazz = clazz.getSuperclass();
}
classLoaderClassesField.setAccessible(true);

List classes = new ArrayList((Vector)classLoaderClassesField.get(classLoader));

for (Object o : classes) {
    Class c = (Class)o;
    //Make sure you identify only the packages that are holding references to the classloader.
    //Allowing this code to clear all static references will result in all sorts
    //of horrible things (like java segfaulting).
    if (c.getName().startsWith("com.whatever")) {
        //Kill any static references within all these classes.
        for (Field f : c.getDeclaredFields()) {
            if (Modifier.isStatic(f.getModifiers())
                    && !Modifier.isFinal(f.getModifiers())
                    && !f.getType().isPrimitive()) {
                try {
                    f.setAccessible(true);
                    f.set(null, null);
                } catch (Exception exception) {
                    //Log the exception
                }
            }
        }
    }
}

classes.clear();

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

К счастью, есть очень простое решение - переместить весь код, который в данный момент находится в методе shutdown, в метод run нового объекта Thread. Затем в методе завершения работы запустите этот поток и дождитесь его завершения. Код очистки будет выполняться одинаково, но любые локальные переменные потока будут оставаться связанными с загрузчиком классов контекста, а не с утечкой.
Эдвард Торбетт

20

java.lang.OutOfMemoryError: PermGenПространство сообщений указывает на то, что площадь Постоянного Поколение в памяти будет исчерпан.

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

Память Java разделена на различные области, которые можно увидеть на следующем рисунке:

введите описание изображения здесь

Metaspace: рождается новое пространство памяти

JVK HotSpot JDK 8 теперь использует собственную память для представления метаданных класса и называется Metaspace; похож на Oracle JRockit и IBM JVM.

Хорошая новость заключается в том, что это означает, что больше не будет java.lang.OutOfMemoryError: PermGenпроблем с пространством и вам больше не нужно настраивать и отслеживать это пространство памяти с помощью Java_8_Download или выше.


17

1) Увеличение объема памяти PermGen

Первое, что можно сделать, - это увеличить размер кучи постоянного поколения. Это невозможно сделать с помощью обычных аргументов JVM –Xms (установить начальный размер кучи) и –Xmx (установить максимальный размер кучи), поскольку, как уже упоминалось, пространство кучи постоянного поколения полностью отделено от обычного пространства кучи Java, и эти аргументы устанавливаются пространство для этого обычного пространства кучи Java. Однако есть аналогичные аргументы, которые можно использовать (по крайней мере для jvms Sun / OpenJDK), чтобы увеличить размер кучи постоянного поколения:

 -XX:MaxPermSize=128m

По умолчанию это 64м.

2) Включить Sweeping

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

-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled

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

Вы можете найти детали этой ошибки.

http://faisalbhagat.blogspot.com/2014/09/java-outofmemoryerror-permgen.html


Отличный пост @faisalbhagat faisalbhagat.blogspot.com/2014/09/…
leomeurer

Вариант 2 хорош, но просто предупреждаем, что его не следует использовать в производственных средах. Как правило, лучше всего хранить его только в средах разработки. Однако PermGen удален с Java 8 openjdk.java.net/jeps/122
hdost

16

Кроме того, вы можете переключиться на JRockit, который обрабатывает permgen иначе, чем Sun JVM. Как правило, он также имеет лучшую производительность.

http://www.oracle.com/technetwork/middleware/jrockit/overview/index.html


4
Хотя у JRockit действительно нет PermGen, но это не поможет в долгосрочной перспективе. Вы получите java.lang.OutOfMemoryError: There is insufficient native memoryвместо этого.
stracktracer

14

У меня была проблема, о которой мы здесь говорим, мой сценарий eclipse-helios + tomcat + jsf, и вы делали развертывание простого приложения для tomcat. Я показывал здесь ту же проблему, решил ее следующим образом.

В eclipse перейдите на вкладку серверов двойным щелчком мыши по зарегистрированному серверу в моем случае tomcat 7.0, он откроет для моего файлового сервера общие регистрационные данные. В разделе «Общая информация» перейдите по ссылке «Открыть конфигурацию запуска» , это откроет выполнение параметров сервера на вкладке Аргументы в аргументах виртуальной машины, добавленных в конце этих двух записей.

-XX: MaxPermSize = 512m
-XX: PermSize = 512m

и готово.


14

Самый простой ответ в наши дни - использовать Java 8.

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

Имейте в виду, что вам придется удалить все нестандартные -XXPermGen...=...параметры запуска JVM, если вы не хотите, чтобы Java 8 жаловалась, что они ничего не делают.


Здравствуйте, этот ответ уже был дан: stackoverflow.com/a/22897121/505893 . Пожалуйста, удалите ваш ответ, для ясности. При необходимости вы можете улучшить ответ, который я упомянул. Спасибо;)
голубоватый

6
@bluish Спасибо, что указали на это; однако, этот ответ идет вбок при разговоре об исключениях OutOfMemoryException и утечке метаданных. Также не упоминаются очень важные моменты удаления опции PermGen. Короче говоря, я не уверен, что улучшил бы ответ, а переписал бы его. Если бы это была просто быстрая подправка, я бы почувствовал себя менее нерешительно, но, похоже, это было бы гораздо больше, чем быстрая подправка, и я бы не хотел обидеть оригинального автора. Тем не менее, этот список ответов - собачий ужин в беспорядке, и, возможно, в любом случае лучше было бы убить мой пост.
Эдвин Бак,

8
  1. Откройте tomcat7w из каталога bin Tomcat или введите Monitor Tomcat в меню «Пуск» (откроется окно с вкладками с различной служебной информацией).
  2. В текстовой области Параметры Java добавьте эту строку:

    -XX:MaxPermSize=128m
  3. Установите начальный пул памяти на 1024 (необязательно).
  4. Установите Максимальный пул памяти на 1024 (необязательно).
  5. Нажмите ОК.
  6. Перезапустите сервис Tomcat.

6

Ошибка Пермского пространства возникает из-за использования большого пространства, а не пространства, предоставленного jvm для выполнения кода.

Лучшее решение этой проблемы в операционных системах UNIX - изменить некоторые настройки в файле bash. Следующие шаги решают проблему.

Запустите команду gedit .bashrcна терминале.

Создайте JAVA_OTPSпеременную со следующим значением:

export JAVA_OPTS="-XX:PermSize=256m -XX:MaxPermSize=512m"

Сохраните файл bash. Запустите команду exec bash на терминале. Перезагрузите сервер.

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


5

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


5

Также, если вы используете log4j в своем веб-приложении, проверьте этот параграф в документации log4j .

Кажется, что, если вы используете PropertyConfigurator.configureAndWatch("log4j.properties"), вы вызываете утечки памяти при удалении вашего веб-приложения.


4

У меня есть комбинация Hibernate + Eclipse RCP, пробовал использовать -XX:MaxPermSize=512mи, -XX:PermSize=512mкажется, это работает для меня.


4

Set -XX:PermSize=64m -XX:MaxPermSize=128m. Позже вы также можете попробовать увеличить MaxPermSize. Надеюсь, это сработает. То же самое работает для меня. Установка только MaxPermSizeне работала для меня.


4

Я попробовал несколько ответов, и единственной вещью, которая наконец сделала работу, была эта конфигурация для плагина компилятора в pom:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.3.2</version>
    <configuration>
        <fork>true</fork>
        <meminitial>128m</meminitial>
        <maxmem>512m</maxmem>
        <source>1.6</source>
        <target>1.6</target>
        <!-- prevent PermGen space out of memory exception -->
        <!-- <argLine>-Xmx512m -XX:MaxPermSize=512m</argLine> -->
    </configuration>
</plugin>

надеюсь, это поможет


"argLine" не распознается плагином maven-compiler-plugin 2.4. он поддерживает только «compilerArgument», который выдает ошибку: <compilerArgument> -XX: MaxPermSize = 256m </ compilerArgument> [ОШИБКА] Сбой при выполнении javac, но не удается проанализировать ошибку: javac: недопустимый флаг: -XX: MaxPermSize = 256m Использование : javac <опции> <исходные файлы>
Алекс

Если ваша фаза компиляции заканчивается permgen, установите <compilerArgument> в maven-compiler-plugin. Если модульные тесты исчерпывают множества PermGen <argLine> в Maven-плагин-верный
QWERTY

4

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


3

Конфигурация памяти зависит от характера вашего приложения.

Что делаешь?

Какое количество транзакций обработано?

Сколько данных вы загружаете?

и т.п.

и т.п.

так далее

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

По-видимому, это может произойти после повторного развертывания приложения несколько раз

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


3

Они говорят, что последняя версия Tomcat (6.0.28 или 6.0.29) намного лучше справляется с задачей повторного развертывания сервлетов .


3

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

В моем случае проблема возникала каждый раз в одно и то же время во время выполнения моего веб-приложения при подключении (через спящий режим) к базе данных.

Эта ссылка (также упоминавшаяся ранее) предоставила достаточно внутренностей для решения проблемы. Перемещение jdbc- (mysql) -драйвера из WEB-INF в папку jre / lib / ext /, похоже, решило проблему. Это не идеальное решение, так как обновление до новой JRE потребует переустановки драйвера. Другим кандидатом, который может вызвать аналогичные проблемы, является log4j, так что вы можете переместить и этот.


Если вы не хотите включать драйвер в jre / lib / ext, вы можете получить те же результаты, включив драйвер в путь к классу при запуске контейнера. java -cp /path/to/jdbc-mysql-driver.jar:/path/to/container/bootstrap.jar container.Start
шотландец

3

Первый шаг в таком случае - проверить, разрешено ли GC выгружать классы из PermGen. Стандартная JVM довольно консервативна в этом отношении - классы рождены, чтобы жить вечно. Поэтому после загрузки классы остаются в памяти, даже если их больше не использует ни один код. Это может стать проблемой, когда приложение создает много классов динамически, и сгенерированные классы не нужны в течение более длительных периодов времени. В таком случае может помочь JVM выгрузить определения классов. Это может быть достигнуто путем добавления только одного параметра конфигурации в ваши сценарии запуска:

-XX:+CMSClassUnloadingEnabled

По умолчанию для этого параметра установлено значение false, поэтому для его включения необходимо явно указать следующую опцию в параметрах Java. Если вы включите CMSClassUnloadingEnabled, GC также будет сканировать PermGen и удалять классы, которые больше не используются. Имейте в виду, что этот параметр будет работать только в том случае, если UseConcMarkSweepGC также включен с использованием указанного ниже параметра. Поэтому при запуске ParallelGC или, не дай Бог, Serial GC, убедитесь, что вы установили GC на CMS, указав:

-XX:+UseConcMarkSweepGC

3

Назначение Tomcat дополнительной памяти НЕ является правильным решением.

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

Если ваш сервер Tomcat / Webapp сообщает вам, что не удалось отменить регистрацию драйверов (JDBC), отмените их регистрацию. Это остановит утечки памяти.

Вы можете создать ServletContextListener и настроить его в своем файле web.xml. Вот пример ServletContextListener:

import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.apache.log4j.Logger;

import com.mysql.jdbc.AbandonedConnectionCleanupThread;

/**
 * 
 * @author alejandro.tkachuk / calculistik.com
 *
 */
public class AppContextListener implements ServletContextListener {

    private static final Logger logger = Logger.getLogger(AppContextListener.class);

    @Override
    public void contextInitialized(ServletContextEvent arg0) {
        logger.info("AppContextListener started");
    }

    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
        logger.info("AppContextListener destroyed");

        // manually unregister the JDBC drivers
        Enumeration<Driver> drivers = DriverManager.getDrivers();
        while (drivers.hasMoreElements()) {
            Driver driver = drivers.nextElement();
            try {
                DriverManager.deregisterDriver(driver);
                logger.info(String.format("Unregistering jdbc driver: %s", driver));
            } catch (SQLException e) {
                logger.info(String.format("Error unregistering driver %s", driver), e);
            }

        }

        // manually shutdown clean up threads
        try {
            AbandonedConnectionCleanupThread.shutdown();
            logger.info("Shutting down AbandonedConnectionCleanupThread");
        } catch (InterruptedException e) {
            logger.warn("SEVERE problem shutting down AbandonedConnectionCleanupThread: ", e);
            e.printStackTrace();
        }        
    }
}

И вот вы настраиваете это в своем файле web.xml:

<listener>
    <listener-class>
        com.calculistik.mediweb.context.AppContextListener 
    </listener-class>
</listener>  

2

«Они» не правы, потому что я работаю 6.0.29 и у меня та же проблема, даже после установки всех параметров. Как сказал Тим Хоулэнд выше, эти варианты только откладывают неизбежное. Они позволяют мне выполнить повторное развертывание 3 раза, прежде чем совершать ошибку, а не каждый раз, когда я выполняю повторное развертывание.


2

В случае, если вы получаете это в IDE eclipse, даже после установки параметров --launcher.XXMaxPermSizeи -XX:MaxPermSizeт. Д., Все же, если вы получаете ту же ошибку, наиболее вероятно, что eclipse использует ошибочную версию JRE, которая была бы установлена ​​некоторыми сторонние приложения и установить по умолчанию. Эти версии с ошибками не принимают параметры PermSize, поэтому независимо от того, что вы установили, вы все равно будете получать эти ошибки памяти. Итак, в ваш eclipse.ini добавьте следующие параметры:

-vm <path to the right JRE directory>/<name of javaw executable>

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


2

Единственный способ, который работал для меня, был с JRockit JVM. У меня есть MyEclipse 8.6.

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


2

У меня была похожая проблема. Мой JDK 7 + Maven 3.0.2 + Struts 2.0 + Google GUICE проект, основанный на внедрении зависимостей.

Всякий раз, когда я пытался запустить mvn clean packageкоманду, она показала следующую ошибку, и "BUILD FAILURE" происходило

org.apache.maven.surefire.util.SurefireReflectionException: java.lang.reflect.InvocationTargetException; вложенным исключением является java.lang.reflect.InvocationTargetException: null java.lang.reflect.InvocationTargetException, вызванный: java.lang.OutOfMemoryError: пространство PermGen

Я испробовал все вышеперечисленные полезные советы и рекомендации, но, к сожалению, ни один из них не помог мне. То, что сработало для меня, описано шаг за шагом ниже: =>

  1. Перейти к вашему pom.xml
  2. Ищи <artifactId>maven-surefire-plugin</artifactId>
  3. Добавьте новый <configuration>элемент, а затем <argLine>вложенный элемент, в котором передайте, -Xmx512m -XX:MaxPermSize=256mкак показано ниже =>

<configuration> <argLine>-Xmx512m -XX:MaxPermSize=256m</argLine> </configuration>

Надеюсь, это поможет, счастливого программирования :)

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.