Алгоритмы, которые приводят к java.lang.OutOfMemoryError: Ошибка пространства PermGen - PullRequest
2 голосов
/ 04 октября 2010

Я получаю ошибку пространства PermGen на Sun JVM (1.6.0_21-b06) (хорошо, это Oracle :)).Увеличение параметра -XX: значение MaxPermGen не помогает.Я знаю, что PermGen - это пространство, предназначенное для постоянных объектов, таких как метаданные класса.Количество классов в проекте не так велико ~ 10 000. Перед сбоем jvisualvm показывает 57MB как Used PermGen.

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

UPD. Я задаю такой абстрактный вопрос, потому что в данный момент я не могу использовать какой-либо профилировщик - код падает так сильно, что jvisualvmзатмение перестать отвечать.Мне нужно, чтобы убить процессы Java из терминала с помощью kill -KILL {process_numer}.Я работаю с плохо организованным (но коммерческим) кодом, который имеет много потоков и сообщений JMS.Отладка - это беспорядок - сначала нужно понять, где искать.

Ответы [ 6 ]

4 голосов
/ 04 октября 2010

Это не столько алгоритм, сколько его реализация.Вот действительно глупый способ генерировать случайные строки, которые заполняют пространство PermGen:

    Random rnd = new Random();
    List<String> interned = new ArrayList<String>();
    for (;;) {
        int length = rnd.nextInt(100);
        StringBuilder builder = new StringBuilder();
        String chars = "abcdefghijklmnopqrstuvwxyz";
        for ( int i = 0; i < length; i++ ) {
            builder.append(chars.charAt(rnd.nextInt(chars.length())));
        }
        interned.add(builder.toString().intern());
    }

Вкратце: интернирование строк - это одна вещь, которая может поглотить память PermGen.

3 голосов
/ 04 октября 2010

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

  1. Метод String.intern(String) создает строки в куче PermGen.Если вы выполняете много интернирования и прямо (или косвенно) сохраняете ссылки на интернированные строки, вы можете заполнить PermGen.

  2. Загрузчики классов создают дескрипторы внутренних классов JVM и сегменты кода в PermGenкуча.Если ваше приложение выполняет динамическую загрузку классов, а объекты класса не собирают мусор, вы можете заполнить PermGen.

Горячее повторное развертывание веб-приложений Java зависит от динамической загрузки и является распространенным источником проблем PermGen.Основной причиной обычно является утечка памяти, которая включает в себя скрытую ссылку из какого-либо объекта на старый загрузчик классов.(Tomcat часто получает «залипание» за это, но реальная проблема, как правило, в том, что веб-приложение перераспределяется.)

AFAIK, случай с Proxy, упомянутый @Michael Borgwardt, также является результатом генерации реализации Proxyфайлы классов и загрузка их на лету.

1 голос
/ 04 октября 2010

Проверить анализатор памяти - http://www.eclipse.org/mat/. Это анализатор дампа памяти Java.Это очень полезно после неожиданной ошибки.

1 голос
/ 04 октября 2010

Кто-нибудь знает примеры алгоритмов, которые приводят к переполнению PermGen?

Да, но какой в ​​этом смысл?если вы хотите это исправить, установите инструмент профилирования памяти, такой как jprobe или lambda probe, и проверьте, где происходит утечка памяти, и исправьте это.Теперь для примера: есть тысячи способов превзойти пространство перманента.Я заметил в проекте, когда мы унаследовали приложение, в котором они использовали JMS.Соединения jms были оставлены открытыми, приложение рухнуло через несколько минут после того, как было получено много запросов с такой же ошибкой, как и вы.Обратите внимание: когда мы перешли на weblogic из jboss (перешел на beajrockit), он удивительным образом исправился или, по крайней мере, получил удар технического долга.Мой совет был бы, независимо от этого, сначала нужно исправить плохой код с утечками памяти, а затем поработать с серверами приложений и параметрами выделения пространства кучи.

Вот полезная ссылка с некоторой информацией о полученном вами исключении.http://www.jroller.com/agileanswers/entry/preventing_java_s_java_lang

РЕДАКТИРОВАТЬ

Эта ссылка может быть полезной http://www.precisejava.com/javaperf/j2ee/JMS.htm

1 голос
/ 04 октября 2010

Если вы используете java.lang.reflect.Proxy очень интенсивно, это также может поглотить ваше пространство PermGen.

0 голосов
/ 04 октября 2010

Вы используете другой сборщик мусора?

Сборщик пропускной способности выдает исключение нехватки памяти, если слишком много времени тратится на сборку мусора. Например, если JVM тратит более 98% общего времени на сборку мусора и восстанавливает менее 2% кучи, это приведет к нехватке памяти. Реализация этой функции изменилась в 1.5. Политика такая же, но могут быть небольшие различия в поведении из-за новой реализации ».« В платформе J2SE версии 1.5 в качестве сборщика мусора на компьютерах серверного класса будет выбран сборщик мусора ».

Проверьте некоторые инструкции на этой странице.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...