Ошибка размещения сборщика мусора в Java

Я запускаю Java-приложение на компьютере с 8 ГБ памяти и 4 процессорами. Но после запуска приложения в течение более длительного периода со стресс-тестированием наблюдаются проблемы сборщика мусора, поскольку память полностью заполнена, и кажется, что циклы gc требуют больше времени для завершения, но я не могу выяснить возможную причину и способы ее устранения. Нет большой разницы в средней задержке наших запросов на выполнение. Но он не может обслуживать много потоков одновременно.

Я начал свою заявку со следующими параметрами

-Xms4096M -Xmx4096M 
-XX:MaxPermSize=512M 
-XX:PermSize=512m 
-XX:+UseConcMarkSweepGC 
-XX:+HeapDumpOnOutOfMemoryError 
-XX:+PrintGCTimeStamps 
-XX:+PrintGCDetails 
-XX:+PrintGCApplicationStoppedTime 
-XX:+PrintGCApplicationConcurrentTime 
-XX:+PrintHeapAtGC 
-Xloggc:/root/tomcat_logs/gc_logs.log

Вывод верхней команды

top - 11:24:03 up 44 days, 23:45,  1 user,  load average: 0.39, 0.47, 0.65
Tasks: 158 total,   1 running, 157 sleeping,   0 stopped,   0 zombie
Cpu(s): 18.8%us,  2.1%sy,  0.0%ni, 64.2%id, 12.9%wa,  0.2%hi,  1.8%si,  0.0%st
Mem:   7672012k total,  7270396k used,   401616k free,   238468k buffers
Swap:  5238776k total,    34584k used,  5204192k free,  2390820k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                           
15811 root      20   0 7919m 4.1g   9m S 101.1 55.9   4134:37 java 

Образец GC Logs после заполнения памяти

{Heap before GC invocations=193901 (full 4):
 par new generation   total 306688K, used 274312K [0x00000006c0000000, 0x00000006d4cc0000, 0x00000006d4cc0000)
  eden space 272640K, 100% used [0x00000006c0000000, 0x00000006d0a40000, 0x00000006d0a40000)
  from space 34048K,   4% used [0x00000006d2b80000, 0x00000006d2d222c8, 0x00000006d4cc0000)
  to   space 34048K,   0% used [0x00000006d0a40000, 0x00000006d0a40000, 0x00000006d2b80000)
 concurrent mark-sweep generation total 3853568K, used 687930K [0x00000006d4cc0000, 0x00000007c0000000, 0x00000007c0000000)
 Metaspace       used 58528K, capacity 59902K, committed 61732K, reserved 1103872K
  class space    used 6866K, capacity 7109K, committed 7464K, reserved 1048576K
89974.407: [GC (Allocation Failure) 89974.407: [ParNew: 274312K->1655K(306688K), 0.0101861 secs] 962243K->689622K(4160256K), 0.0104010 secs] [Times: user=0.04 sys=0.00, real=0.01 secs] 
Heap after GC invocations=193902 (full 4):
 par new generation   total 306688K, used 1655K [0x00000006c0000000, 0x00000006d4cc0000, 0x00000006d4cc0000)
  eden space 272640K,   0% used [0x00000006c0000000, 0x00000006c0000000, 0x00000006d0a40000)
  from space 34048K,   4% used [0x00000006d0a40000, 0x00000006d0bdded0, 0x00000006d2b80000)
  to   space 34048K,   0% used [0x00000006d2b80000, 0x00000006d2b80000, 0x00000006d4cc0000)
 concurrent mark-sweep generation total 3853568K, used 687966K [0x00000006d4cc0000, 0x00000007c0000000, 0x00000007c0000000)
 Metaspace       used 58528K, capacity 59902K, committed 61732K, reserved 1103872K
  class space    used 6866K, capacity 7109K, committed 7464K, reserved 1048576K
}
89974.418: Total time for which application threads were stopped: 0.0127352 seconds
89974.988: Application time: 0.5703336 seconds

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

2 ответа

В основном вы сталкиваетесь с возможной утечкой памяти. С YourKIt (или профилировщиком по вашему выбору) запустите ваше приложение и со временем выполните принудительный сбор мусора через равные промежутки времени, а затем проверьте, какие объекты все еще накапливаются, несмотря на силу gc. Это может быть трудоемким занятием, но в итоге окупится.

Возможной причиной могут быть утечки ClassLoader, слабые ссылки, плохо реализованное кэширование или что-то еще.

Нет проблем, видимых из выдержки из журнала, которую вы представили.

[Время: пользователь =0,04 сис =0,00, реальное =0,01 с]

Сбор занял 10мс времени.

общее число одновременных генераций с разметкой 3853568K, использовано 687966K [0x00000006d4cc0000, 0x00000007c0000000, 0x00000007c0000000)

старое поколение - всего 680 МБ /3,8 ГБ.

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

Возможно, вы захотите запустить все это через GCViewer, чтобы увидеть, действительно ли вы испытываете проблемы с GC.

Другие вопросы по тегам