Усунення з помилкою "java.lang.OutOfMemoryError: PermGen space"


1222

Нещодавно я зіткнувся з цією помилкою у своєму веб-додатку:

java.lang.OutOfMemoryError: PermGen space

Це типова програма Hibernate / JPA + IceFaces / JSF, що працює на Tomcat 6 та JDK 1.6. Мабуть, це може статися після повторного розміщення програми кілька разів.

Що це викликає і що можна зробити, щоб цього уникнути? Як виправити проблему?


Я боровся з цим годинами, але не маю гарних новин. Дивіться моє відповідне запитання: stackoverflow.com/questions/1996088/… Можливо, у вас все ще виникає витік пам’яті, наприклад, класи не збирають сміття, оскільки ваш WebAppClassLoader не зібраний сміття (на нього є зовнішня посилання, яка не очищена). збільшення PermGen лише затримає OutOfMemoryError, і дозволити збирання сміття класів є необхідною умовою, але не буде збирати сміття класів, якщо їх завантажувач класів все ще має посилання на нього.
Еран Медан

Я отримав цю помилку при додаванні таліб дисплея . Видалення також вирішило помилку. Чому так?
masT

І як ти наткнувся на це?
Thorbjørn Ravn Andersen

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

де ім'я_служби це ім'я сервера , як показано на services.msc

Джерело: коментар orx до Agile відповідей Еріка .


39
Стаття нижче пропонує -XX: + UseConcMarkSweepGC і -XX: MaxPermSize = 128 м. 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 "- Відновлюється tomcat, використовуючи: sudo /etc/init.d/tomcat6 start
самі

24
Під час запуску tomcat 6.0.29 з мого файлу catalina.out: "Будь ласка, використовуйте CMSClassUnloadingEnabled замість CMSPermGenSweepingEnabled у майбутньому"
knb

222
По-перше, було б чудово пояснити, що справді роблять ці прапори. Тільки сказати: "роби це і насолоджуйся" недостатньо ІМХО.
Nikem

251

Ви краще спробуйте -XX:MaxPermSize=128M, ніж ніж -XX:MaxPermGen=128M.

Я не можу сказати точне використання цього пулу пам'яті, але це стосується кількості класів, завантажених в JVM. (Таким чином, включення розвантаження класу для tomcat може вирішити проблему.) Якщо ваші програми генерують та компілюють класи під час запуску, швидше за все, знадобиться пул пам'яті, більший за замовчуванням.


9
Насправді це лише відкладе OOMError. Дивіться відповідь нижче, розпочату анонсом з двома посиланнями на blog frankkieviet
Rade_303

Ці варіанти описані тут: oracle.com/technetwork/java/javase/tech / ...
Амосса

153

Помилки PermGen сервера додатків, які трапляються після декількох розгортань, швидше за все, викликані посиланнями, що зберігаються контейнером, у завантажувачі старих додатків. Наприклад, використання користувальницького класу рівня журналу призведе до того, що посилання зберігатимуться класним завантажувачем сервера додатків. Ви можете виявити ці витоки міжкласового завантажувача, скориставшись сучасними інструментами аналізу JVM (JDK6 +), такими як jmap та jhat, щоб переглянути, які класи продовжують утримуватися у вашому додатку, а також переробити або усунути їх використання. Звичайними підозрюваними є бази даних, реєстратори та інші бібліотеки базового рівня.

Див. Витоки Classloader: жахливий виняток "java.lang.OutOfMemoryError: PermGen space" , і особливо його наступний пост .


3
Це єдино вірне рішення проблеми, яке в деяких випадках занадто важко реалізувати.
Rade_303

Ще одне дуже хороше джерело - люди.apache.org/~markt/presentations/… (від менеджера випуску Tomcat !!).
gavenkoa

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

68

Загальні помилки, які люди роблять, - це думка про те, що купа простору і пермген простір однакові, що зовсім не так. У вас може залишитися багато місця в купі, але все одно у вас не вистачить пам’яті в пермі.

Поширені причини OutofMemory в PermGen - це ClassLoader. Щоразу, коли клас завантажується в JVM, всі його метадані разом із Classloader зберігаються на PermGen області, і вони будуть збирати сміття, коли Classloader, який завантажив їх, буде готовий до вивезення сміття. У випадку Case 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. Моя версія tomcat є 5.5.26.
Декард

Як знайти витоки пам'яті завантажувача класу? Чи рекомендуєте ви будь-який інструмент?
Аміт

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

@Deckard заходить у каталог Tomcat / bin та працює tomcat6w.exe. На вкладці «Java» додайте аргументи у вікно «Параметри Java». Натисніть "ОК"
Zeb

43

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


9
Єдине питання полягає в тому, що ти просто затягуєш неминуче - в якийсь момент ти теж закінчишся із зал. Це чудове прагматичне рішення, але воно не вирішує його назавжди.
Тім Хоуленд

те ж саме відбувається в Eclipse і в будь-який час у вас є багато динамічного завантаження класу. навантажувачі не розміщені та живуть у постійному поколінні цілу вічність
Метт,

1
Мені не вистачало PermGen під час виконання особливо великої роботи Гудсона ... це вирішило це для мене.
HDave

10
@TimHowland, це може бути постійним виправленням, якщо першопричиною є не витік завантажувача класу, просто занадто багато класів / статичних даних у вашому веб-додатку.
Péter Török

отримали те саме питання, що і HDave, коли створювали дженкіни / гудзони з джерела.
louisgab

38

Спробуйте, -XX:MaxPermSize=256mі якщо це зберігається, спробуйте-XX:MaxPermSize=512m


56
і якщо це все ще зберігається, спробуйте XX:MaxPermSize=1024m:)
igo

38
і якщо це все ще зберігається, спробуйте XX: MaxPermSize = 2048м :)
Томас

16
І якщо вона ВІДПОВІДАЄ, перегляньте свою заявку !! Або спробуйте XX: MaxPermSize = 4096 м :)
Джонатан Ейрі

17
Ви також можете спробувати 8192 м, але це трохи
непосидючості

12
Справді надмірність - 640 КБ нікому не вистачить!
Джоел Пурра

28

Я додав -XX: MaxPermSize = 128m (ви можете експериментувати, який найкраще працює) до аргументів В.М., коли я використовую ідею затемнення. У більшості JVM за замовчуванням PermSize становить близько 64 Мб, що не вистачає пам'яті, якщо в проекті занадто багато класів або величезна кількість рядків.

Для затемнення це також описано у відповіді .

КРОК 1 : Двічі клацніть на сервері tomcat на вкладці Сервери

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

КРОК 2 : Відкрийте запуск Conf та додайте -XX: MaxPermSize = 128mдо кінця існуючі аргументи VM .

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


1
Дякую за найкращу детальну відповідь (Примітка: натисніть "Відкрити конфігурацію запуску", щоб відкрити вікно "редагувати конфігурацію" ... але я використав такі параметри: "-XX: + CMSClassUnloadingEnabled -XX: + CMSPermGenSweepingEnabled"
Chris Sim

23

Я також мав голову проти цієї проблеми під час розгортання та нерозгортання складного веб-додатка, і думав, що я додам пояснення та своє рішення.

Коли я розгортаю програму на Apache Tomcat, для цього додатка створюється новий ClassLoader. Потім ClassLoader використовується для завантаження всіх класів програми, а в режимі неелектричної роботи все повинно пройти непогано. Однак насправді це не так просто.

Один або кілька класів, створених протягом життя веб-програми, містить статичну довідку, яка десь уздовж лінії посилається на ClassLoader. Оскільки посилання спочатку статична, жодна кількість збирання сміття не очистить цю довідку - ClassLoader та всі класи, які вона завантажує, залишаються тут.

І після пари повторних розборок ми стикаємося з OutOfMemoryError.

Зараз це стало досить серйозною проблемою. Я міг би переконатися, що Tomcat перезапускається після кожного повторного розгортання, але це забирає весь сервер, а не лише перепрограмування програми, що часто неможливо.

Тому замість цього я зібрав рішення в коді, яке працює на Apache Tomcat 6.0. Я не тестувався на будь-яких інших серверах прикладних програм, і потрібно наголосити, що це, швидше за все, не працює без змін на будь-якому іншому сервері додатків .

Я також хотів би сказати, що особисто я ненавиджу цей код, і що ніхто не повинен використовувати це як "швидке виправлення", якщо існуючий код можна змінити для використання правильних методів відключення та очищення . Єдиний раз, коли це слід використати, це якщо є зовнішня бібліотека, від якої залежить ваш код (у моєму випадку це був клієнт RADIUS), який не забезпечує засоби для очищення власних статичних посилань.

У всякому разі, з кодом. Це слід викликати у тому випадку, коли додаток не працює, наприклад, метод знищення сервлета або (кращий підхід) метод контекстування Devstroy 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 років, як я написав це, але десь між тим часом і тепер я знайшов глибшу першопричину і рішення. Це було те, що, хоча всі класи в webapp належать завантажувачу контексту, потоком, який викликає зворотний виклик при запуску та відключенні, належить батьківський клас завантажувач. Це означає, що якщо код відключення ініціалізує локальну змінну потоку, це призведе до того, що батьківський завантажувач в кінцевому підсумку містить посилання на контекстний завантажувач, що запобігає гарному очищенню.
Едвард Торбетт

На щастя, існує дуже просте виправлення - перемістити весь код, який зараз знаходиться в методі відключення, в новий метод запуску об'єкта Thread. Потім у способі відключення запустіть цю нитку і дочекайтеся її завершення. Код очищення буде виконуватися однаково, але будь-які змінні локальні потоки залишаться прив’язаними до завантажувача контексту замість протікання.
Едвард Торбетт

20

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

Будь-які програми Java можуть використовувати обмежений об'єм пам'яті. Точний об'єм пам'яті, яку може використовувати ваша конкретна програма, визначається під час запуску програми.

Пам'ять Java розділена на різні регіони, що можна побачити на наступному зображенні:

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

Метапростір: народжується новий простір пам'яті

Тепер JVM JDK HotSpot використовує вбудовану пам'ять для представлення метаданих класу і називається Metaspace; схожий на Oracle JRockit та IBM JVM.

Хороша новина полягає в тому, що це більше не має java.lang.OutOfMemoryError: PermGenпроблем з простором і не потрібно більше налаштовувати та контролювати цей простір пам'яті за допомогою Java_8_Download або вище.


17

1) Збільшення розміру пам'яті PermGen

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

 -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

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

16

Крім того, ви можете переключитися на JRockit, який керує пермгеном інакше, ніж сонячний 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. Я показував ту саму проблему, вирішував її так.

У затемнення йти вкладку серверів двічі клацніть на зареєстрованому сервері, в моєму випадку tomcat 7.0, він відкриє мій файловий сервер Загальна інформація про реєстрацію. У розділі "Загальна інформація" натисніть посилання "Відкрити конфігурацію запуску" , це відкриє виконання параметрів сервера на вкладці "Аргументи" в аргументах VM, доданих в кінці цих двох записів.

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

і готовий.


14

Найпростішою відповіддю в ці дні є використання Java 8.

Він більше не резервує пам'ять виключно для простору PermGen, що дозволяє пам’яті PermGen поєднуватися зі звичайним пулом пам’яті.

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


Привіт, цю відповідь уже надано: stackoverflow.com/a/22897121/505893 . Будь ласка, видаліть свою відповідь для наочності. Якщо потрібно, ви можете вдосконалити відповідь, яку я згадав. Спасибі;)
синюватий

6
@bluish Дякую, що вказали на це; однак ця відповідь іде вбік, коли йдеться про OutOfMemoryExceptions та протікають метадані. Він також не згадує про дуже важливі моменти усунення параметра PermGen. Коротше кажучи, я не впевнений, що би вдосконалив відповідь, а скоріше переписав би її. Якби це було лише швидке підключення, я б почувався менш вагаючись, але, схоже, це було б набагато більше, ніж швидке підключення, і я б ненавиджу образити оригінального автора. І все-таки цей список відповідей - це собачий обід безладу, і, мабуть, найкраще вбити мою посаду.
Едвін Бак

8
  1. Відкрийте tomcat7w з каталогу сміття 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

Встановити -XX:PermSize=64m -XX:MaxPermSize=128m. Пізніше ви також можете спробувати збільшити MaxPermSize. Сподіваюся, це спрацює. Те саме працює і для мене. Налаштування MaxPermSizeне працювало для мене.


4

Я спробував кілька відповідей, і єдине, що нарешті зробило цю роботу, це конфігурація плагіну компілятора у пам’яті:

<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 <options> <вихідні файли>
Alex

Якщо у вашій фазі компіляції закінчується permgen, встановіть <compilerArgument> на maven-компілятор-плагін. Якщо в одиниці тестів закінчується набір permgen <argLine> в плагіні Maven-surefire
qwerty

4

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


3

Конфігурація пам’яті залежить від характеру вашої програми.

Що ви робите?

Яка сума попередніх операцій?

Скільки даних ви завантажуєте?

тощо.

тощо.

тощо

Можливо, ви могли б профілювати свою програму і почати прибирати деякі модулі зі свого додатка.

Мабуть, це може статися після повторного розміщення програми кілька разів

Tomcat має гаряче розгортання, але він споживає пам'ять. Спробуйте перезавантажити контейнер раз у раз. Крім того, вам потрібно буде знати об'єм пам'яті, необхідний для запуску у виробничому режимі, це здається сприятливим часом для цього дослідження.


3

Вони кажуть, що остання версія Tomcat (6.0.28 або 6.0.29) справляється із завданням перерозподілити сервлетів набагато краще.


3

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

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

Цей посилання (також згадувалося раніше) мало достатньо для вирішення проблеми. Переміщення jdbc- (mysql) -driver з 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
Scot

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 затемнення, навіть після встановлення параметрів --launcher.XXMaxPermSizeі -XX:MaxPermSizeт. Д., Все-таки якщо ви отримуєте ту ж помилку, швидше за все, це, що затемнення використовує помилкову версію JRE, яку встановили б деякі сторонні програми та встановлено за замовчуванням. Ці помилкові версії не підбирають параметри PermSize, тому незалежно від того, що ви встановили, ви все одно отримуєте ці помилки пам'яті. Отже, у ваш eclipse.ini додайте такі параметри:

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

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


2

Єдиний спосіб, який працював для мене, - це JVockit 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 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>

Сподіваюся, це допомагає, раді програмування :)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.