Hung JVM потребляет 100% процессор

У нас есть JAVA-сервер, работающий на Sun JRE 6u20 на 32-разрядной версии Linux (CentOS). Мы используем серверную точку доступа с сборщиком CMS со следующими параметрами (я предоставил только соответствующие):

-Xmx896m -Xss128k -XX:NewSize=384M -XX:MaxPermSize=96m -XX:+UseParNewGC -XX:+UseConcMarkSweepGC

Иногда, по прошествии некоторого времени, JVM, похоже, проскальзывает в завитое состояние, и, хотя мы не делаем никаких запросов к приложению, процессор продолжает вращаться на 100% (у нас есть 8 логических процессоров, поэтому похоже, что только один процессор делает вращение). В этом состоянии JVM не отвечает на сигналы SIGHUP (kill -3), и мы не можем нормально подключаться к нему с помощью jstack. Мы можем подключиться к "jstack -F", но результат является изворотливым (мы можем видеть множество NullPointerExceptions из JStack, по-видимому, потому, что он не смог "пройти" несколько стеков). Таким образом, вывод "jstack -F" кажется бесполезным.

Мы запустили дамп стека из "gdb", и мы смогли сопоставить идентификатор потока, который вращает процессор (мы обнаружили, что использование "top" с представлением в потоке - опция "H" ) с поток стека, который появляется в результате gdb, и вот как это выглядит:

Thread 443 (Thread 0x7e5b90 (LWP 26310)):
#0  0x0115ebd3 in CompactibleFreeListSpace::block_size(HeapWord const*) const () from /usr/java/jdk1.6.0_20/jre/lib/i386/server/libjvm.so
#1  0x01160ff9 in CompactibleFreeListSpace::prepare_for_compaction(CompactPoint*) () from /usr/java/jdk1.6.0_20/jre/lib/i386/server/libjvm.so
#2  0x0123456c in Generation::prepare_for_compaction(CompactPoint*) () from /usr/java/jdk1.6.0_20/jre/lib/i386/server/libjvm.so
#3  0x01229b2c in GenCollectedHeap::prepare_for_compaction() () from /usr/java/jdk1.6.0_20/jre/lib/i386/server/libjvm.so
#4  0x0122a7fc in GenMarkSweep::invoke_at_safepoint(int, ReferenceProcessor*, bool) () from /usr/java/jdk1.6.0_20/jre/lib/i386/server/libjvm.so
#5  0x01186024 in CMSCollector::do_compaction_work(bool) () from /usr/java/jdk1.6.0_20/jre/lib/i386/server/libjvm.so
#6  0x011859ee in CMSCollector::acquire_control_and_collect(bool, bool) () from /usr/java/jdk1.6.0_20/jre/lib/i386/server/libjvm.so
#7  0x01185705 in ConcurrentMarkSweepGeneration::collect(bool, bool, unsigned int, bool) () from /usr/java/jdk1.6.0_20/jre/lib/i386/server/libjvm.so
#8  0x01227f53 in GenCollectedHeap::do_collection(bool, bool, unsigned int, bool, int) () from /usr/java/jdk1.6.0_20/jre/lib/i386/server/libjvm.so
#9  0x0115c7b5 in GenCollectorPolicy::satisfy_failed_allocation(unsigned int, bool) () from /usr/java/jdk1.6.0_20/jre/lib/i386/server/libjvm.so
#10 0x0122859c in GenCollectedHeap::satisfy_failed_allocation(unsigned int, bool) () from /usr/java/jdk1.6.0_20/jre/lib/i386/server/libjvm.so
#11 0x0158a8ce in VM_GenCollectForAllocation::doit() () from /usr/java/jdk1.6.0_20/jre/lib/i386/server/libjvm.so
#12 0x015987e6 in VM_Operation::evaluate() () from /usr/java/jdk1.6.0_20/jre/lib/i386/server/libjvm.so
#13 0x01597c93 in VMThread::evaluate_operation(VM_Operation*) () from /usr/java/jdk1.6.0_20/jre/lib/i386/server/libjvm.so
#14 0x01597f0f in VMThread::loop() () from /usr/java/jdk1.6.0_20/jre/lib/i386/server/libjvm.so
#15 0x015979f0 in VMThread::run() () from /usr/java/jdk1.6.0_20/jre/lib/i386/server/libjvm.so
#16 0x0145c24e in java_start(Thread*) () from /usr/java/jdk1.6.0_20/jre/lib/i386/server/libjvm.so
#17 0x00ccd46b in start_thread () from /lib/libpthread.so.0
#18 0x00bc2dbe in clone () from /lib/libc.so.6

Кажется, что поток JVM вращается, выполняя некоторую работу, связанную с CMS. Мы проверили использование памяти на коробке, кажется, достаточно свободного места, и система не меняет местами. Кто-нибудь сталкивался с такой ситуацией? Это похоже на ошибку JVM?

UPDATE

Я получил дополнительную информацию об этой проблеме (это произошло снова на сервере, который работает более 7 дней). Когда JVM вошел в состояние "зависания", он оставался таким же в течение 2 часов, пока сервер не был перезагружен вручную. Мы получили базовый дамп процесса и gc log. Мы также попытались получить кучу кучи, но "jmap" потерпел неудачу. Мы пытались использовать jmap -F, но только файл размером 4 МБ был написан до того, как программа была прервана с исключением (что-то о том, что ячейка памяти не доступна). До сих пор я думаю, что самая интересная информация поступает из журнала gc. Похоже, что журнал GC остановился (возможно, в то время, когда поток VM перешел в длинный цикл):

657501.199: [Full GC (System) 657501.199: [CMS: 400352K->313412K(524288K), 2.4024120 secs] 660634K->313412K(878208K), [CMS Perm : 29455K->29320K(68568K)], 2.4026470 secs] [Times: user=2.39 sys=0.01, real=2.40 secs] 
657513.941: [GC 657513.941: [ParNew: 314624K->13999K(353920K), 0.0228180 secs] 628036K->327412K(878208K), 0.0230510 secs] [Times: user=0.08 sys=0.00, real=0.02 secs] 
657523.772: [GC 657523.772: [ParNew: 328623K->17110K(353920K), 0.0244910 secs] 642036K->330523K(878208K), 0.0247140 secs] [Times: user=0.08 sys=0.00, real=0.02 secs] 
657535.473: [GC 657535.473: [ParNew: 331734K->20282K(353920K), 0.0259480 secs] 645147K->333695K(878208K), 0.0261670 secs] [Times: user=0.11 sys=0.00, real=0.02 secs] 
....
....
688346.765: [GC [1 CMS-initial-mark: 485248K(524288K)] 515694K(878208K), 0.0343730 secs] [Times: user=0.03 sys=0.00, real=0.04 secs] 
688346.800: [CMS-concurrent-mark-start]
688347.964: [CMS-concurrent-mark: 1.083/1.164 secs] [Times: user=2.52 sys=0.09, real=1.16 secs] 
688347.964: [CMS-concurrent-preclean-start]
688347.969: [CMS-concurrent-preclean: 0.004/0.005 secs] [Times: user=0.00 sys=0.01, real=0.01 secs] 
688347.969: [CMS-concurrent-abortable-preclean-start]
 CMS: abort preclean due to time 688352.986: [CMS-concurrent-abortable-preclean: 2.351/5.017 secs] [Times: user=3.83 sys=0.38, real=5.01 secs] 
688352.987: [GC[YG occupancy: 297806 K (353920 K)]688352.987: [Rescan (parallel) , 0.1815250 secs]688353.169: [weak refs processing, 0.0312660 secs] [1 CMS-remark: 485248K(524288K)] 783055K(878208K), 0.2131580 secs] [Times: user=1.13 sys
=0.00, real=0.22 secs] 
688353.201: [CMS-concurrent-sweep-start]
688353.903: [CMS-concurrent-sweep: 0.660/0.702 secs] [Times: user=0.91 sys=0.07, real=0.70 secs] 
688353.903: [CMS-concurrent-reset-start]
688353.912: [CMS-concurrent-reset: 0.008/0.008 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
688354.243: [GC 688354.243: [ParNew: 344928K->30151K(353920K), 0.0305020 secs] 681955K->368044K(878208K), 0.0308880 secs] [Times: user=0.15 sys=0.00, real=0.03 secs]
....
....
688943.029: [GC 688943.029: [ParNew: 336531K->17143K(353920K), 0.0237360 secs] 813250K->494327K(878208K), 0.0241260 secs] [Times: user=0.10 sys=0.00, real=0.03 secs] 
688950.620: [GC 688950.620: [ParNew: 331767K->22442K(353920K), 0.0344110 secs] 808951K->499996K(878208K), 0.0347690 secs] [Times: user=0.11 sys=0.00, real=0.04 secs] 
688956.596: [GC 688956.596: [ParNew: 337064K->37809K(353920K), 0.0488170 secs] 814618K->515896K(878208K), 0.0491550 secs] [Times: user=0.18 sys=0.04, real=0.05 secs] 
688961.470: [GC 688961.471: [ParNew (promotion failed): 352433K->332183K(353920K), 0.1862520 secs]688961.657: [CMS

Я подозреваю, что эта проблема имеет какое-то отношение к последней строке в журнале (я добавил некоторые "....", чтобы пропустить некоторые строки, которые не были интересными). Тот факт, что сервер остался в состоянии зависания в течение 2 часов (вероятно, пытаясь GC и уплотнить старое поколение), кажется мне довольно странным. Кроме того, журнал gc неожиданно останавливается с этим сообщением, и больше ничего не печатается, возможно, потому, что поток VM попадает в какой-то бесконечный цикл (или что-то, что занимает 2 часа).

Ответ 1

Похоже, проблема настройки GC, возможно, вызвана утечкой памяти. Я предлагаю вам добавить параметр JVM, который включает журнал GC, и посмотреть, дает ли это вам какие-либо идеи.

Это похоже на ошибку JVM?

Не для меня.

Когда вы закончите кучу пространства (например, в результате утечки хранилища), обычно наблюдается, что GC работает все чаще и чаще, и использует больший и больший процент CPU. Есть некоторые параметры JVM, которые вы можете установить, чтобы избежать этого, но они могут привести к тому, что ваш JVM будет кипеть раньше с OOME. (Это может показаться странным, но во многих случаях это хорошо, потому что это сокращает время до перезапуска вашей системы и может нормально работать снова.)

Ответ 2

У меня также есть эта проблема на Linux 64-bit Fedora15. Я запускаю tomcat, используя JSVC на порту 80. И несколько раз jvm зависает, принимая 100% процессор. Но когда я запускаю

jmap -F -histo [tomcat-pID] 

все возвращается к норме.

Я читаю http://mail-archives.apache.org/mod_mbox/tomcat-users/200305.mbox/%[email protected]%3E

Но эта проблема возникла внезапно без каких-либо изменений в кодовой базе.