У меня есть приложение Grails, которое в основном используется как WebService. Он обеспечивает очень настраиваемый тип кэширования, при котором объекты хранятся в параллельной хэш-карте в течение нескольких секунд и потенциально объединяются, прежде чем они могут быть обработаны другим потоком. После нескольких месяцев работы без проблем пространство PermGen в конечном итоге достигает своего максимума, и мне нужно перезапустить сервер, чтобы предотвратить исключение OOMError.
Я не думаю, что моя проблема связана с утечкой загрузчиков классов, которая, по-видимому, является причиной большинства проблем с PermGen. Я никогда не переустанавливаю это приложение. PermGen заполняется только при обычном использовании.
У меня есть ощущение, что моя проблема может быть связана с большим количеством уникальных строк, которые обрабатывает мое приложение. Мое приложение интенсивно использует GStrings как для ведения журнала, так и для обработки перед сохранением в хэш-карте, например:
mOrig.msg += mNew.msg
log.debug("Sending combined message: ${mOrig.msg}")
Мой вопрос заключается в том, используют ли записи GString или Hashmap String.intern(). Если это так, я думаю, это объясняет, почему мое пространство PermGen заполняется. Если это действительно так, как лучше всего справиться с этим? Я уже увеличил объем пространства PermGen в аргументах JVM. Однако это лишь оттягивает неизбежное.
Я использовал Eclipse Memory Analyzer для сравнения дампов кучи после месяца использования. Хотя это мало что говорит мне об использовании PermGen, было ясно, что самая большая разница между двумя кучами — это количество строк и записей Hashmap.
Class Name | Objects | Shallow Heap
--------------------------------------------------------------------------
| |
char[] | +1,731 | +268,984
byte[] | +35 | +142,240
java.util.HashMap$Entry | +1,684 | +80,832
java.lang.String | +1,675 | +67,000
org.apache.tomcat.util.buf.ByteChunk | +202 | +12,928
org.apache.tomcat.util.buf.MessageBytes | +146 | +11,680
org.apache.tomcat.util.buf.CharChunk | +162 | +9,072
java.lang.Object[] | -31 | +7,840
java.text.DecimalFormat | +32 | +6,912
int[] | +87 | +6,824
java.lang.String[] | +68 | +5,872
Кто-нибудь знает, что здесь может быть и как с этим бороться? Я хотел бы избежать перезапуска Tomcat каждые несколько недель/месяцев.
Спасибо!
ОБНОВЛЕНИЕ: Добавлен вывод из jmap -permstat
. Кто-нибудь знает, как это читать?
29045 intern Strings occupying 4025008 bytes.
class_loader classes bytes parent_loader alive? type
<bootstrap> 2221 12948256 null live <internal>
0x00002aaac0c40048 1 1952 0x00002aaabe2108a8 dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaac0c3c388 10 211456 0x00002aaac04f0cc8 dead org/codehaus/groovy/runtime/callsite/CallSiteClassLoader@0x00002aaaaf4cf338
0x00002aaac1a2c698 1 3112 0x00002aaabe2108a8 dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaac0159380 1 3128 0x00002aaac04f0cc8 dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaac0158a28 1 3096 0x00002aaac04f0cc8 dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaac1dfa188 1 3248 0x00002aaac04f0cc8 dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaac1a2f910 1 1952 0x00002aaabe2108a8 dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaac0c6e390 12 239656 null dead org/codehaus/groovy/runtime/callsite/CallSiteClassLoader@0x00002aaaaf4cf338
0x00002aaac1df0a68 1 3200 0x00002aaac0afd9b8 dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaac1a2db68 1 3112 0x00002aaabe2108a8 dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaac1a36f58 1 3112 0x00002aaabe2108a8 dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaac1df9688 1 1952 null dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaac0171e70 1 1968 0x00002aaac04f0cc8 dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaac1979200 1 1952 null dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaac01712a8 1 1952 0x00002aaac04f0cc8 dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaac1dec140 1 3096 0x00002aaac04f0cc8 dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaac197ad80 1 1952 null dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaac1df13e8 1 3120 null dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaac1a2f1a0 1 1952 0x00002aaabe2108a8 dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaac197c380 1 1952 null dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaac0c451c0 1 1952 0x00002aaabe2108a8 dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaabe2183b8 4 14192 null dead javax/management/remote/rmi/NoCallStackClassLoader@0x00002aaaae81ef70
0x00002aaabfd24688 1 1952 0x00002aaac04f0cc8 dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaabecd6250 2 19984 0x00002aaabe2108a8 dead org/apache/catalina/loader/WebappClassLoader@0x00002aaaaee35f48
0x00002aaabe217da0 94 900176 0x00002aaabe210930 dead sun/misc/Launcher$AppClassLoader@0x00002aaaae446690
0x00002aaac0170f68 1 1952 0x00002aaac04f0cc8 dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaac0c43bc0 1 1952 0x00002aaabe2108a8 dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaac0c45d60 1 3112 0x00002aaabe2108a8 dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaac1df0e68 1 1968 null dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaac01716b8 1 1952 0x00002aaac04f0cc8 dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaac1a35c58 1 3112 0x00002aaabe2108a8 dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaac0c462e0 1 1952 0x00002aaabe2108a8 dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaac0c87750 1 1968 null dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaac1a2e4b0 1 3112 0x00002aaabe2108a8 dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaabfd246f0 1 3128 0x00002aaac04f0cc8 dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaac1de9830 1 3136 null dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaac1982680 1 3120 null dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20
0x00002aaac0171a60 1 3112 null dead sun/reflect/DelegatingClassLoader@0x00002aaaae276b20