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

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

java.lang.OutOfMemoryError: PermGen space

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

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

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

masT 14.11.2013 15:51

А как вы с этим столкнулись?

Thorbjørn Ravn Andersen 25.02.2014 08:16

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

Rytek 20.03.2014 20:25

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

Eran Medan 14.01.2010 14:48

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

MacGyver 24.02.2017 19:55
Знайте свои исключения!
Знайте свои исключения!
В Java исключение - это событие, возникающее во время выполнения программы, которое нарушает нормальный ход выполнения инструкций программы. Когда...
Управление ответами api для исключений на Symfony с помощью KernelEvents
Управление ответами api для исключений на Symfony с помощью KernelEvents
Много раз при создании api нам нужно возвращать клиентам разные ответы в зависимости от возникшего исключения.
1 230
5
1 036 944
32
Перейти к ответу Данный вопрос помечен как решенный

Ответы 32

Ответ принят как подходящий

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

-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled

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

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

tomcat6w //ES//servicename

где наименование услуги - имя сервера, как показано в services.msc

Источник: комментарий orx к Гибкие ответы Эрика.

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

Taylor Leese 27.05.2009 22:51

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

Eldelshell 03.09.2010 13:16

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

sami 10.12.2010 17:44

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

knb 27.07.2011 15:59

На tomcat 5.5 в Ubuntu я изменил /etc/default/tomcat5.5 следующим образом: JAVA_OPTS = "- Djava.awt.headless = true -Xms128M -Xmx512M -XX: + CMSClassUnloadingEnabled -XX: MaxPermSize = 128m"

stivlo 30.07.2011 22:40

Я не могу открыть tomcat6w.exe :( Он говорит: «Указанная служба не существует как установленная. Невозможно открыть службу tomcat6». Может ли кто-нибудь помочь мне в этом?

false9striker 14.03.2012 10:03

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

Nikem 23.07.2012 15:44

Во-вторых, если ваше приложение действительно пропускает загрузчик классов, то есть оставляет где-то объект или класс, загруженный загрузчиком классов приложения, даже после отмены развертывания, эти флаги не помогут. Я написал сообщение в блоге об этом и других предложениях в этой теме: plumbr.eu/blog/busting-permgen-myths

Nikem 23.07.2012 15:46

-XX: + CMSClassUnloadingEnabled и -XX: + CMSPermGenSweepingEnabled неприменимы в java 1.7, см. связь

Marko Vranjkovic 15.05.2013 19:32

@lolotron, с Java OpenJDK 64-Bit Server VM (build 24.45-b08, mixed mode) ... запущенным java -XX:+PrintFlagsFinal -version ... возвращенный список флагов включает CMSClassUnloadingEnabled.

Abdull 27.12.2013 01:58

@lolotron вульгарно пытается установить его на tomcat 7 на «Java HotSpot (TM) Server VM (сборка 24.45-b08, смешанный режим)», он работает нормально (ошибок OutOfMemory больше нет).

reallynice 23.07.2014 19:08

Чтобы узнать больше о флагах - stackoverflow.com/questions/3334911/…

Senthil Kumar 25.11.2014 04:09

Немного устарело, как этот поток, но вот документация от Oracle: oracle.com/technetwork/java/…

J Slick 27.10.2015 20:54

Я могу сделать это на tomcat 7: добавить эту строку в setenv.sh [JAVA_OPTS = "- Xms256m -Xmx512m -XX: + CMSClassUnloadingEnabled -XX: + CMSPermGenSweepingEnabled"]? это сработает?

Ali Issa 03.12.2015 12:39

что сработало для меня в окнах: создал файл ${tomcat-folder}\bin\setenv.bat, содержащий одну строку: set JAVA_OPTS=-Dfile.encoding=UTF-8 -Xms128m -Xmx1024m -XX:PermSize=64m -XX:MaxPermSize=256m

Kai Carver 22.03.2016 10:32

Правильным решением является устранение проблем с утечкой памяти и их устранение. Если вы зарегистрировали драйверы JDBC, отмените их регистрацию. Вы можете использовать javax.servlet.ServletContextListener. Я опубликовал решение ниже с образцом кода для отмены регистрации драйверов / потоков / т. Д.

Alejandro Pablo Tkachuk 25.04.2016 20:18

Что, если я использую WebLogic?

LucaP 16.05.2017 18:06

Обратите внимание, что CMSClassUnloadingEnabled по умолчанию включен.

Rostislav V 08.08.2017 16:33

По какой-либо причине они не включены по умолчанию?

jonasespelita 30.07.2018 07:08

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

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

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

stracktracer 27.07.2012 11:25

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

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

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

Tim Howland 18.09.2008 07:35

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

Matt 23.09.2008 00:48

У меня заканчивались PermGen при выполнении особенно большого задания Hudson ... это исправило это для меня.

HDave 31.10.2011 19:15

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

Péter Török 14.12.2011 12:50

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

louisgab 27.02.2014 00:27

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

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

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

Rade_303 07.06.2012 21:21

Еще один очень хороший источник - people.apache.org/~markt/presentations/… (из диспетчера выпуска Tomcat !!).

gavenkoa 22.12.2012 21:49

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

Joachim Sauer 09.04.2013 14:30

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

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

igo 12.04.2013 12:30

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

Thomas 31.07.2013 14:49

И если это все еще не исчезнет, ​​пересмотрите свое приложение !! Или попробуйте XX: MaxPermSize = 4096m :)

Jonathan Airey 06.10.2014 15:25

вы также можете попробовать 8192 м, но это немного перебор

Jacek Pietal 16.10.2014 20:24

В самом деле, перебор - 640 КБ должно хватить любому!

Joel Purra 24.03.2015 16:35

давайте посмотрим ... 2012 ppl скажем 1024, 2013 - 2048, 2014 это было 4096 и 2015 приходит на 8192. Теперь просто потратьте эти 100 долларов на ваш 16384.

gzmask 09.12.2016 11:00

Ну, у меня была такая же проблема, поэтому все, что я сделал, это XX: MaxPermSize = 131072m :)

lpkej 05.05.2020 21:42

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

Что делаешь?

Какой объем транзакций предварительно обработан?

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

и Т. Д.

и Т. Д.

так далее

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

Apparently this can occur after redeploying an application a few times

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

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

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

Фактически, это только отложит OOMError. См. Ответ ниже, начатый анонимом, с двумя ссылками на блог frankkieviet.

Rade_303 07.06.2012 21:23

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

amos 13.02.2014 22:27

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

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

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

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

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

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

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

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

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

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

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

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

и готово.

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

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

Эта ссылка (также упомянутый ранее) действительно предоставил достаточно внутренних компонентов для решения проблемы. Перемещение драйвера 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.Start

Scot 29.05.2014 01:01

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

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

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

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

Edward Torbett 05.09.2019 17:56

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

Edward Torbett 05.09.2019 18:01

Я попробовал несколько ответов, и единственное, что в итоге сработало, - это конфигурация плагина компилятора в 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> [ERROR] Ошибка при выполнении javac, но не удалось проанализировать ошибку: javac: недопустимый флаг: -XX: MaxPermSize = 256m Usage : javac <параметры> <исходные файлы>

Alex 22.05.2012 23:47

Если на этапе компиляции заканчивается permgen, установите <compilerArgument> в maven-compiler-plugin. Если у модульных тестов заканчивается permgen, установите <argLine> в maven-surefire-plugin

qwerty 11.02.2014 14:25

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

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

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

Вы также можете проверить 2 Решение Java.lang.OutOfMemoryError в Java для получения дополнительных сведений.

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

Deckard 20.01.2012 05:15

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

Amit 04.09.2014 15:13

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

Barett 23.04.2015 21:35

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

Zeb 19.10.2016 12:19

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

Вы также можете решить эту проблему, выполнив:

rm -rf <tomcat-dir>/work/* <tomcat-dir>/temp/*

Очистка каталогов работай и темп заставляет Tomcat выполнять чистый запуск.

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

Для eclipse это также описано в отвечать.

ШАГ 1: дважды щелкните сервер tomcat на вкладке Серверы

ШАГ 2: Открыть запуск Conf и добавьте -XX: MaxPermSize = 128m в конец существующего Аргументы ВМ.

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

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

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

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

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

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

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

bluish 07.08.2014 16:54

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

Edwin Buck 07.08.2014 17:01

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

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

 -XX:MaxPermSize=128m

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

2) Включить развертку

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

-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled

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

Вы можете найти подробную информацию об этой ошибке.

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

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

leomeurer 17.10.2014 20:59

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

hdost 16.04.2015 08:05

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

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

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

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

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

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

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

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

Всякий раз, когда я пытался запустить команду mvn clean package, она показывала следующую ошибку, и происходило «СТРОИТЬ ОТКАЗ»

org.apache.maven.surefire.util.SurefireReflectionException: java.lang.reflect.InvocationTargetException; nested exception is java.lang.reflect.InvocationTargetException: null java.lang.reflect.InvocationTargetException Caused by: java.lang.OutOfMemoryError: PermGen space

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

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

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

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

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

-XX:+CMSClassUnloadingEnabled

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

-XX:+UseConcMarkSweepGC

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

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

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

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

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

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

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

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

Если ваш Tomcat / Webapp Server сообщает вам, что не удалось отменить регистрацию драйверов (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>  

Если кто-то борется с той же ошибкой в ​​netbeans, то вот как я ее исправил.

В Netbeans:

Перейдите на вкладку служб -> Прямо на сервере -> Выберите свойства -> перейдите на вкладку платформы -> Тип параметров внутри vm -Xms1024m

В моем случае я дал -Xms4096m

Вот скриншот:

Другие вопросы по теме