2015-03-01 4 views
3

я вижу следующее из «jmap -permstat»:мертвых загрузчиков классов не мусор, собранные из PermGen

0x000000077736cce0  12  173472 0x00000007723425d0  dead com/sun/org/apache/xalan/internal/xsltc/trax/[email protected] 
0x0000000777168a20  12  172264 0x00000007723425d0  dead com/sun/org/apache/xalan/internal/xsltc/trax/[email protected] 
0x0000000780b3c810  12  172264 0x00000007723425d0  dead com/sun/org/apache/xalan/internal/xsltc/trax/[email protected] 
0x0000000776ca6170  12  172264 0x00000007723425d0  dead com/sun/org/apache/xalan/internal/xsltc/trax/[email protected] 
0x00000007772b28a8  12  172264 0x00000007723425d0  dead com/sun/org/apache/xalan/internal/xsltc/trax/[email protected] 
.... 

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

java.lang.OutOfMemoryError: PermGen space

у меня есть следующий набор флагов JVM:

-XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSClassUnloadingEnabled

java version "1.6.0_33" 
Java(TM) SE Runtime Environment (build 1.6.0_33-b04) 
Java HotSpot(TM) 64-Bit Server VM (build 20.8-b03, mixed mode) 

Почему эти погрузчики мертвого класса не очищаются с помощью флага CMSClassUnloadingEnabled? Как исправить эту проблему?

ответ

4

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

  • Вы создаете новый ClassLoader
  • You классы нагрузки в новом загрузчиком классов
  • создать экземпляр одного из классов.
  • Вы помещаете экземпляр в структуру данных (например), что делает его постоянно достижимым.
  • Вы отказываетесь от ссылки на загрузчик классов.

Проблема заключается в том, что до сих пор, как экземпляр, который вы создали достижима, нам нужно 1) код для классов методов экземпляра, 2) Class объекта (или Infor, чтобы сделать это) в случае, если кто-то называет getClass() на примере.

Это означает, что (по сути) класс должен быть доступен.

Но у Class есть метод getClassloader, поэтому объект classloader также должен быть доступен.

И типичный объект classloader имеет внутренние ссылки на все классы, которые он загружал, поэтому они также должны быть доступны.


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

+0

Обратите внимание, что «ссылка» на ClassB может просто состоять в том, что ClassA имеет нулевую ссылочную переменную типа ClassB или содержит вызов метода, который имеет параметр ClassB. И даже не обязательно быть экземпляром ClassA.Это означает, что вы * всегда * должны использовать схему поиска по имени для ссылки на ClassB на что-то вне своего загрузчика классов и всегда должны использовать интерфейсы или суперклассы для ссылки на свои экземпляры. –

+0

Что может привести к отказу Classloader? –

+0

ClassLoader может собирать только мусор, когда он становится недоступным. –

1

В качестве последующего действия для Stephens anser вы можете посмотреть на this blog series of mine, чтобы узнать, как отследить утечку загрузчика класса. Или вы можете просто пропустить и добавить my Classloader Leak Prevention library в ваше приложение.

Удачи вам!

P.S. Если вы отлаживаете его и обнаруживаете утечку внутри Xalan, сообщите мне, чтобы я мог обновить the list of known offenders.