Java.lang.OutOfMemoryError: сжатое пространство класса

Мы работаем над java-8-oracle.

Мы переехали в java8 шесть месяцев назад.

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

Когда мы выполняем вызов сервера (tomcat), мы получаем эту ошибку на стеке:

java.lang.OutOfMemoryError: Compressed class space

Перезапуск сервера решает проблему. Тот же вызов на другом сервере работает, и другой вызов другого типа на тот же сервер.

При просмотре gc.log мы видим:

2015-05-27T16:05:42.991+0000: 98774.440: [Full GC (Last ditch collection) 98774.440: [CMS: 575745K->575330K(3495936K), 0.8687777 secs] 575745K->575330K(4107008K), [Metaspace: 97940K->97940K(1396736K)], 0.8696093 secs] [Times: user=0.95 sys=0.00, real=0.88 secs]
2015-05-27T16:05:55.486+0000: 98786.935: [Full GC (Metadata GC Threshold) 98786.935: [CMS: 573414K->578735K(3495936K), 0.9372859 secs] 925046K->578735K(4107008K), [Metaspace: 99428K->99428K(1396736K)], 0.9386626 secs] [Times: user=1.01 sys=0.00, real=0.94 secs]

jstat -gc возвращает:

 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
87296.0 87296.0  0.0   3151.4 523776.0 148284.4 3495936.0   574868.5  1395640.0 98066.3 1048576.0 11339.1  12165  636.851  223   116.957  

753.808

Я не вижу проблем с памятью либо в журнале jstat, либо в журнале gc.

Попытка запуска jmap -clstats зависает:

Attaching to process ID 5110, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.25-b02
finding class loader instances ..

Ответ 1

Мы столкнулись с подобной проблемой. К сожалению, heapdumps не помогут вам, поскольку классы не находятся в куче, а в собственной памяти. Включите их в настройках JVM, чтобы устранить загруженные классы:

-XX: + PrintGCDetails -XX: + TraceClassUnloading -XX: + TraceClassLoading

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

Удачи, Альберт

Ответ 2

С сжатыми oops и сжатыми указателями класса доступное пространство для классов ограничено из-за необходимого манипулирования указателем. 1GB в вашем случае.

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

Если вы уверены, что вашему приложению просто требуется столько памяти для классов, вы можете попробовать преодолеть лимит с помощью -XX:CompressedClassSpaceSize=... или отключить сжатые указатели класса через -XX:-UseCompressedClassPointers.

Обратите внимание, что по умолчанию сжатое пространство класса + сжатая куча (+ некоторые служебные данные) не может превышать 32 ГБ. Хотя, AIUI, изменение выравнивания объекта может привести к тому, что ограничение еще больше.

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