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


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

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

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

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


1177


источник


Ответы:


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

-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled

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

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

tomcat6w //ES//servicename

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

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


549



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

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


247



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

Видеть Утечка загрузчика класса: страшное исключение «java.lang.OutOfMemoryError: PermGen space» , и особенно его последующий пост ,


152



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

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

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

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


65



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


39



Try -XX:MaxPermSize=256m and if it persists, try -XX:MaxPermSize=512m


35



I added -XX: MaxPermSize = 128m (you can experiment which works best) to VM Arguments as I'm using eclipse ide. In most of JVM, default PermSize is around 64MB which runs out of memory if there are too many classes or huge number of Strings in the project.

For eclipse, it is also described at answer.

STEP 1 : Double Click on the tomcat server at Servers Tab

enter image description here

STEP 2 : Open launch Conf and add -XX: MaxPermSize = 128m to the end of existing VM arguements.

enter image description here


24



I've been butting my head against this problem while deploying and undeploying a complex web application too, and thought I'd add an explanation and my solution.

When I deploy an application on Apache Tomcat, a new ClassLoader is created for that app. The ClassLoader is then used to load all the application's classes, and on undeploy, everything's supposed to go away nicely. However, in reality it's not quite as simple.

One or more of the classes created during the web application's life holds a static reference which, somewhere along the line, references the ClassLoader. As the reference is originally static, no amount of garbage collecting will clean this reference up - the ClassLoader, and all the classes it's loaded, are here to stay.

And after a couple of redeploys, we encounter the OutOfMemoryError.

Now this has become a fairly serious problem. I could make sure that Tomcat is restarted after each redeploy, but that takes down the entire server, rather than just the application being redeployed, which is often not feasible.

So instead I've put together a solution in code, which works on Apache Tomcat 6.0. I've not tested on any other application servers, and must stress that this is very likely not to work without modification on any other application server.

I'd also like to say that personally I hate this code, and that nobody should be using this as a "quick fix" if the existing code can be changed to use proper shutdown and cleanup methods. The only time this should be used is if there's an external library your code is dependent on (In my case, it was a RADIUS client) that doesn't provide a means to clean up its own static references.

Anyway, on with the code. This should be called at the point where the application is undeploying - such as a servlet's destroy method or (the better approach) a ServletContextListener's contextDestroyed method.

//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();

22



Alternatively, you can switch to JRockit which handling permgen differently then sun's jvm. It generally has better performance as well.

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


15



1) Increasing the PermGen Memory Size

The first thing one can do is to make the size of the permanent generation heap space bigger. This cannot be done with the usual –Xms(set initial heap size) and –Xmx(set maximum heap size) JVM arguments, since as mentioned, the permanent generation heap space is entirely separate from the regular Java Heap space, and these arguments set the space for this regular Java heap space. However, there are similar arguments which can be used(at least with the Sun/OpenJDK jvms) to make the size of the permanent generation heap bigger:

 -XX:MaxPermSize=128m

Default is 64m.

2) Enable Sweeping

Another way to take care of that for good is to allow classes to be unloaded so your PermGen never runs out:

-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled

Stuff like that worked magic for me in the past. One thing though, there’s a significant performance trade off in using those, since permgen sweeps will make like an extra 2 requests for every request you make or something along those lines. You’ll need to balance your use with the tradeoffs.

You can find the details of this error.

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


14



I had the problem we are talking about here, my scenario is eclipse-helios + tomcat + jsf and what you were doing is making a deploy a simple application to tomcat. I was showing the same problem here, solved it as follows.

In eclipse go to servers tab double click on the registered server in my case tomcat 7.0, it opens my file server General registration information. On the section "General Information" click on the link "Open launch configuration" , this opens the execution of server options in the Arguments tab in VM arguments added in the end these two entries

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

and ready.


13