a step-by-step approach toward high quality outofmemoryerror analysis

164
© 2016 NetCracker Technology Corporation Confidential Разбор сложных случаев OutOfMemoryError Владимир Ситников JEEConf 2016

Upload: vladimir-sitnikov

Post on 07-Jan-2017

300 views

Category:

Software


1 download

TRANSCRIPT

Page 1: A step-by-step approach toward high quality OutOfMemoryError analysis

© 2016 NetCracker Technology Corporation Confidential

Разбор сложных случаев OutOfMemoryError

Владимир СитниковJEEConf 2016

Page 2: A step-by-step approach toward high quality OutOfMemoryError analysis

2© 2016 NetCracker Technology Corporation Confidential

• Владимир Ситников• Performance engineer @ NetCracker• [email protected]• @VladimirSitnikv

Кто я

Page 3: A step-by-step approach toward high quality OutOfMemoryError analysis

3© 2016 NetCracker Technology Corporation Confidential

О чём доклад

• Разбор некоторых out of memory: OS, JVM• Примеры подходов к анализу/защите от OOM• OpenJDK/OracleJDK

Page 4: A step-by-step approach toward high quality OutOfMemoryError analysis

4© 2016 NetCracker Technology Corporation Confidential

Как понять, что память закончилась?

Видим в логах OutOfMemoryError – значит наш случай• OutOfMemoryError: Java heap space• OutOfMemoryError: heap allocation failed• OutOfMemoryError: PermGen/Metadata space• OutOfMemoryError: unable to create native thread• ...

Page 5: A step-by-step approach toward high quality OutOfMemoryError analysis

5© 2016 NetCracker Technology Corporation Confidential

Дело о потерянном процессе

• Java процесс работал и пропал

Page 6: A step-by-step approach toward high quality OutOfMemoryError analysis

6© 2016 NetCracker Technology Corporation Confidential

Дело о потерянном процессе

• Java процесс работал и пропал• hs_err файл не появился

Page 7: A step-by-step approach toward high quality OutOfMemoryError analysis

7© 2016 NetCracker Technology Corporation Confidential

Дело о потерянном процессе

• Java процесс работал и пропал• hs_err файл не появился• В out, err, log пусто

Page 8: A step-by-step approach toward high quality OutOfMemoryError analysis

8© 2016 NetCracker Technology Corporation Confidential

Дело о потерянном процессе

• Java процесс работал и пропал• hs_err файл не появился• В out, err, log пусто• Как так?

Page 9: A step-by-step approach toward high quality OutOfMemoryError analysis

9© 2016 NetCracker Technology Corporation Confidential

OOMkiller

У Linux память конечна, и если она заканчивается, то может случиться разное:

• умрёт невезучий процесс (по умолчанию)

Page 10: A step-by-step approach toward high quality OutOfMemoryError analysis

10© 2016 NetCracker Technology Corporation Confidential

OOMkiller

У Linux память конечна, и если она заканчивается, то может случиться разное:

• умрёт невезучий процесс (по умолчанию)• malloc вернёт ошибку «нет памяти»

Page 11: A step-by-step approach toward high quality OutOfMemoryError analysis

11© 2016 NetCracker Technology Corporation Confidential

OOMkiller

У Linux память конечна, и если она заканчивается, то может случиться разное:

• умрёт невезучий процесс (по умолчанию)• malloc вернёт ошибку «нет памяти»

Ключевое слово в Linux: vm.overcommit_memory=0

Page 12: A step-by-step approach toward high quality OutOfMemoryError analysis

12© 2016 NetCracker Technology Corporation Confidential

vm.overcommit_memory=0

vm.overcommit_memory=0• Выглядит хорошо (не будет overcommit)

Page 13: A step-by-step approach toward high quality OutOfMemoryError analysis

13© 2016 NetCracker Technology Corporation Confidential

vm.overcommit_memory=0

vm.overcommit_memory=0• Выглядит хорошо (не будет overcommit)• Работает не всегда: многие процессы выделяют,

но не используют память (~fork syscall)

Page 14: A step-by-step approach toward high quality OutOfMemoryError analysis

14© 2016 NetCracker Technology Corporation Confidential

Смотрим потребление памяти

$ top PID VIRT RES COMMAND18133 9606m 7.3g ora_dbw0_DB1132600 2163m 843m /jdk170_55/bin/java -Xmx200m17532 1757m 602m /jdk160_14/bin/java -Xmx1024m

Page 15: A step-by-step approach toward high quality OutOfMemoryError analysis

15© 2016 NetCracker Technology Corporation Confidential

Смотрим потребление памяти

$ top PID VIRT RES COMMAND18133 9606m 7.3g ora_dbw0_DB1132600 2163m 843m /jdk170_55/bin/java -Xmx200m17532 1757m 602m /jdk160_14/bin/java -Xmx1024m$ free –g (http://www.linuxatemyram.com/) total used freeMem: 31 31 0-/+ buffers/cache: 10 21Swap: 8 3 5

Занимаемая память

Свободная память

Page 16: A step-by-step approach toward high quality OutOfMemoryError analysis

16© 2016 NetCracker Technology Corporation Confidential

Смотрим потребление памяти

$ top PID VIRT RES COMMAND18133 9606m 7.3g ora_dbw0_DB1132600 2163m 843m /jdk170_55/bin/java -Xmx200m17532 1757m 602m /jdk160_14/bin/java -Xmx1024m

Page 17: A step-by-step approach toward high quality OutOfMemoryError analysis

17© 2016 NetCracker Technology Corporation Confidential

Следим за native памятью

• -XX:+NativeMemoryTracking=[off|summary|detail]

Page 18: A step-by-step approach toward high quality OutOfMemoryError analysis

18© 2016 NetCracker Technology Corporation Confidential

Следим за native памятью

• -XX:+NativeMemoryTracking=[off|summary|detail]• Работает начиная с 1.7u40

Page 19: A step-by-step approach toward high quality OutOfMemoryError analysis

19© 2016 NetCracker Technology Corporation Confidential

Следим за native памятью

• -XX:+NativeMemoryTracking=[off|summary|detail]• Работает начиная с 1.7u40• Получить разбивку можно через

• jcmd <pid> VM.native_memory <output_file_name>• -XX:+PrintNMTStatistics -XX:+UnlockDiagnosticVMOptions• Или JMX: com.sun.management:type=

DiagnosticCommand/vmNativeMemory

Page 20: A step-by-step approach toward high quality OutOfMemoryError analysis

20© 2016 NetCracker Technology Corporation Confidential

NMT на практике

Page 21: A step-by-step approach toward high quality OutOfMemoryError analysis

21© 2016 NetCracker Technology Corporation Confidential

Ценный мех NMT

NMT позволяет• более адресно заводить тикеты на OpenJDK• проверять наличие утечек «служебной» памятиПример: GROOVY-7498 Groovy native memory leak

Page 22: A step-by-step approach toward high quality OutOfMemoryError analysis

22© 2016 NetCracker Technology Corporation Confidential

Накладные расходы

• В 1.7u40 активация NMT замедляет на 5-10%• http://hirt.se/blog/?p=401

• В 1.8u40 вошла доработка масштабируемости NMT• JEP 195: Scalable Native Memory Tracking

Page 23: A step-by-step approach toward high quality OutOfMemoryError analysis

23© 2016 NetCracker Technology Corporation Confidential

Запускаем процесс

new ProcessBuilder("ping","123.321.123.321") .start();

Page 24: A step-by-step approach toward high quality OutOfMemoryError analysis

24© 2016 NetCracker Technology Corporation Confidential

Запускаем процесс

new ProcessBuilder("ping", "8.8.8.8") .start();

Page 25: A step-by-step approach toward high quality OutOfMemoryError analysis

25© 2016 NetCracker Technology Corporation Confidential

Page 26: A step-by-step approach toward high quality OutOfMemoryError analysis

26© 2016 NetCracker Technology Corporation Confidential

На самом деле, можно

Если версия JDK свежая, то проблем нет:• https://bugs.openjdk.java.net/browse/JDK-5049299• 1.7u60+ всё ок• 1.8u??+ (в 8u60 исправление есть наверняка)

Page 27: A step-by-step approach toward high quality OutOfMemoryError analysis

27© 2016 NetCracker Technology Corporation Confidential

В предыдущих серияхверсиях

• ProcessBuilder#start() использует fork()

• -Xmx8g «по наследству» передаётся в ping• В итоге ping либо не запустится, либо есть

шанс разбудить oomkiller

Page 28: A step-by-step approach toward high quality OutOfMemoryError analysis

28© 2016 NetCracker Technology Corporation Confidential

Как запускать процессы в OpenJDK<1.7u60

• Либо вообще не запускать процессы

Page 29: A step-by-step approach toward high quality OutOfMemoryError analysis

29© 2016 NetCracker Technology Corporation Confidential

Как запускать процессы в OpenJDK<1.7u60

• Либо вообще не запускать процессы• Либо использовать jnr-posix (напрямую или из JRuby)

• https://github.com/jnr/jnr-posix

Page 30: A step-by-step approach toward high quality OutOfMemoryError analysis

30© 2016 NetCracker Technology Corporation Confidential

OutOfMemoryError: unable to create native thread

• Кто виноват?

Page 31: A step-by-step approach toward high quality OutOfMemoryError analysis

31© 2016 NetCracker Technology Corporation Confidential

OutOfMemoryError: unable to create native thread

• Кто виноват?• 32bit JVM и в адресном пространстве уже негде выделить место

для стека (thread native stack)

Page 32: A step-by-step approach toward high quality OutOfMemoryError analysis

32© 2016 NetCracker Technology Corporation Confidential

OutOfMemoryError: unable to create native thread

• Кто виноват?• 32bit JVM и в адресном пространстве уже негде выделить

место для стека (thread native stack)

• Что делать?• Переходить на 64bit JVM

Page 33: A step-by-step approach toward high quality OutOfMemoryError analysis

33© 2016 NetCracker Technology Corporation Confidential

OutOfMemoryError: unable to create native thread

• Кто виноват?• 32bit JVM и в адресном пространстве уже негде выделить

место для стека (thread native stack)

• Что делать?• Переходить на 64bit JVM• Или уменьшать -XX:ThreadStackSize, уменьшать -

XX:MaxPermSize

Page 34: A step-by-step approach toward high quality OutOfMemoryError analysis

34© 2016 NetCracker Technology Corporation Confidential

А какая у нас версия?

$ java -Xmx800m -versionError occurred during initialization of VMjava.lang.OutOfMemoryError: unable to create new native thread at java.lang.Thread.start0(Native Method) at java.lang.Thread.start(Thread.java:714) at java.lang.ref.Finalizer.<clinit>(Finalizer:226)

Page 35: A step-by-step approach toward high quality OutOfMemoryError analysis

35© 2016 NetCracker Technology Corporation Confidential

limits

$ ulimit –a

Page 36: A step-by-step approach toward high quality OutOfMemoryError analysis

36© 2016 NetCracker Technology Corporation Confidential

limits

$ ulimit –avirtual memory (kbytes, -v) unlimited

Page 37: A step-by-step approach toward high quality OutOfMemoryError analysis

37© 2016 NetCracker Technology Corporation Confidential

limits

$ ulimit –avirtual memory (kbytes, -v) unlimitedopen files (-n) 16384

Page 38: A step-by-step approach toward high quality OutOfMemoryError analysis

38© 2016 NetCracker Technology Corporation Confidential

limits

$ ulimit –avirtual memory (kbytes, -v) unlimitedopen files (-n) 16384max user processes (-u) 100000

Page 39: A step-by-step approach toward high quality OutOfMemoryError analysis

39© 2016 NetCracker Technology Corporation Confidential

limits

$ ulimit –avirtual memory (kbytes, -v) unlimitedopen files (-n) 16384max user processes (-u) 100000stack size (kbytes, -s) 10240

Page 40: A step-by-step approach toward high quality OutOfMemoryError analysis

40© 2016 NetCracker Technology Corporation Confidential

Действия в случае OutOfMemoryError

try { "основной_монитор".notifyAll();} catch (OutOfMemoryError e) { log.info("Нужно больше памяти", e);}

Page 41: A step-by-step approach toward high quality OutOfMemoryError analysis

41© 2016 NetCracker Technology Corporation Confidential

Действия в случае OutOfMemoryError

try { "основной_монитор".notifyAll();} catch (OutOfMemoryError e) { log.info("Нужно больше памяти", e);}

Page 42: A step-by-step approach toward high quality OutOfMemoryError analysis

42© 2016 NetCracker Technology Corporation Confidential

Реальные проблемы

• OOM может получить любой поток в любой момент времени

Page 43: A step-by-step approach toward high quality OutOfMemoryError analysis

43© 2016 NetCracker Technology Corporation Confidential

Реальные проблемы

• OOM может получить любой поток в любой момент времени

• Например, ReentrantLock в момент unlock

Page 44: A step-by-step approach toward high quality OutOfMemoryError analysis

44© 2016 NetCracker Technology Corporation Confidential

Реальные проблемы

• OOM может получить любой поток в любой момент времени

• Например, ReentrantLock в момент unlock

• И мы получим вечнозанятую блокировку, сломанную ArrayBlockingQueue, …

Page 45: A step-by-step approach toward high quality OutOfMemoryError analysis

45© 2016 NetCracker Technology Corporation Confidential

Реальные проблемы

• OOM может получить любой поток в любой момент времени

• Например, ReentrantLock в момент unlock• И мы получим вечнозанятую блокировку,

сломанную ArrayBlockingQueue, …• Аналогично и в случае StackOverflowError

Page 46: A step-by-step approach toward high quality OutOfMemoryError analysis

46© 2016 NetCracker Technology Corporation Confidential

В случае аварии

В случае OutOfMemoryError/StackOverflowError гораздо правильнее делать так:• System.exit(146)• -XX:OnError="kill -9 %p"

Page 47: A step-by-step approach toward high quality OutOfMemoryError analysis

47© 2016 NetCracker Technology Corporation Confidential

Реальные проблемы

• Но как же ReentrantLock?

Page 48: A step-by-step approach toward high quality OutOfMemoryError analysis

48© 2016 NetCracker Technology Corporation Confidential

Реальные проблемы

• Но как же ReentrantLock?• JEP 270: Reserved Stack Areas for Critical Sections

доработка включена в JDK9

Page 49: A step-by-step approach toward high quality OutOfMemoryError analysis

49© 2016 NetCracker Technology Corporation Confidential

В случае аварии

В случае OutOfMemoryError/StackOverflowError гораздо правильнее делать так:• java 1.8u92+: JDK-8138745

-XX:+ExitOnOutOfMemory-XX:+CrashOnOutOfMemory

Page 50: A step-by-step approach toward high quality OutOfMemoryError analysis

50© 2016 NetCracker Technology Corporation Confidential

Java heap

• Хранит java объекты, их содержимое

Page 51: A step-by-step approach toward high quality OutOfMemoryError analysis

51© 2016 NetCracker Technology Corporation Confidential

Java heap

• Хранит java объекты, их содержимое

• Очищается сборщиком мусора

Page 52: A step-by-step approach toward high quality OutOfMemoryError analysis

52© 2016 NetCracker Technology Corporation Confidential

Java heap

• Хранит java объекты, их содержимое

• Очищается сборщиком мусора

• Бывает, заканчивается

Page 53: A step-by-step approach toward high quality OutOfMemoryError analysis

53© 2016 NetCracker Technology Corporation Confidential

OutOfMemoryError: PermGen space

• Кто виноват?• Размер PermGen слишком мал• Загружено слишком много классов

Page 54: A step-by-step approach toward high quality OutOfMemoryError analysis

54© 2016 NetCracker Technology Corporation Confidential

OutOfMemoryError: PermGen space

• Кто виноват?• Размер PermGen слишком мал• Загружено слишком много классов

• Что делать?• Увеличивать perm gen: -XX:PermSize=512M -XX:MaxPermSize=512M

• Искать лишние классы: jmap –histo

Page 55: A step-by-step approach toward high quality OutOfMemoryError analysis

55© 2016 NetCracker Technology Corporation Confidential

OutOfMemoryError: PermGen space

• Кто виноват?• Размер PermGen слишком мал• Загружено слишком много классов

• Что делать?• Увеличивать perm gen: -XX:PermSize=512M -XX:MaxPermSize=512M

• Искать лишние классы: jmap –histo• Обновлять java (в 8-ке будет ошибка Metadata space:)

Page 56: A step-by-step approach toward high quality OutOfMemoryError analysis

56© 2016 NetCracker Technology Corporation Confidential

OutOfMemoryError: Java heap space

• Кто виноват?• Выделено мало памяти• Garbage Collector не успел собрать мусор

• Что делать?• Выделять больше памяти: -Xms, -Xmx• Анализировать использование памяти

Page 57: A step-by-step approach toward high quality OutOfMemoryError analysis

57© 2016 NetCracker Technology Corporation Confidential

Как анализировать занятость heap

GC log фиксирует приход-расход памяти по времени

Page 58: A step-by-step approach toward high quality OutOfMemoryError analysis

58© 2016 NetCracker Technology Corporation Confidential

Как анализировать занятость heap

GC log фиксирует приход-расход памяти по времени

• Как собрать: -Xloggc:logs/gc.log, -XX:+PrintGCDetails, и т.д.

Page 59: A step-by-step approach toward high quality OutOfMemoryError analysis

59© 2016 NetCracker Technology Corporation Confidential

Как анализировать занятость heap

GC log фиксирует приход-расход памяти по времени

• Как собрать: -Xloggc:logs/gc.log, -XX:+PrintGCDetails, и т.д.

• Чем смотреть: GCViewer

Page 60: A step-by-step approach toward high quality OutOfMemoryError analysis

60© 2016 NetCracker Technology Corporation Confidential

Как анализировать занятость heap

GC log фиксирует приход-расход памяти по времени

• Как собрать: -Xloggc:logs/gc.log, -XX:+PrintGCDetails, и т.д.

• Чем смотреть: GCViewer

• На что смотреть: «занятость памяти после full gc»

Page 61: A step-by-step approach toward high quality OutOfMemoryError analysis

61© 2016 NetCracker Technology Corporation Confidential

GC лог здорового человека

• 60мс minor, 3sec major паузы

Page 62: A step-by-step approach toward high quality OutOfMemoryError analysis

62© 2016 NetCracker Technology Corporation Confidential

GC лог здорового человека

• 60мс minor, 3sec major паузы

Page 63: A step-by-step approach toward high quality OutOfMemoryError analysis

63© 2016 NetCracker Technology Corporation Confidential

GC лог здорового человека

• 60мс minor, 3sec major паузы

Page 64: A step-by-step approach toward high quality OutOfMemoryError analysis

64© 2016 NetCracker Technology Corporation Confidential

GC лог курильщика

• Сплошные full gc

Page 65: A step-by-step approach toward high quality OutOfMemoryError analysis

65© 2016 NetCracker Technology Corporation Confidential

GC лог курильщика

• Сплошные full gc

Page 66: A step-by-step approach toward high quality OutOfMemoryError analysis

66© 2016 NetCracker Technology Corporation Confidential

Недоперепил

• Бывает, памяти остаётся мало• GC постоянно как-то находит крохи мусора

Page 67: A step-by-step approach toward high quality OutOfMemoryError analysis

67© 2016 NetCracker Technology Corporation Confidential

Недоперепил

• Бывает, памяти остаётся мало• GC постоянно как-то находит крохи мусора• А OutOfMemory всё нет и нет!

Page 68: A step-by-step approach toward high quality OutOfMemoryError analysis

68© 2016 NetCracker Technology Corporation Confidential

Недоперепил

• Бывает, памяти остаётся мало• GC постоянно как-то находит крохи мусора• А OutOfMemory всё нет и нет!• Что делать, шеф?

Page 69: A step-by-step approach toward high quality OutOfMemoryError analysis

69© 2016 NetCracker Technology Corporation Confidential

Варианты действий, когда почти OOM

• Jmap – снимать дамп вручную

Page 70: A step-by-step approach toward high quality OutOfMemoryError analysis

70© 2016 NetCracker Technology Corporation Confidential

Варианты действий, когда почти OOM

• Jmap – снимать дамп вручную• GC overhead limit

Page 71: A step-by-step approach toward high quality OutOfMemoryError analysis

71© 2016 NetCracker Technology Corporation Confidential

Варианты действий, когда почти OOM

• Jmap – снимать дамп вручную• GC overhead limit

• -XX:GCHeapFreeLimit=20 (2 по умолчанию)‒ Если после full GC останется меньше X%, то OOM

Page 72: A step-by-step approach toward high quality OutOfMemoryError analysis

72© 2016 NetCracker Technology Corporation Confidential

Варианты действий, когда почти OOM

• Jmap – снимать дамп вручную• GC overhead limit

• -XX:GCHeapFreeLimit=20 (2 по умолчанию)‒ Если после full GC останется меньше X%, то OOM

• -XX:GCTimeLimit=Y (98 по умолчанию)‒Если сборка мусора занимает более Y%

времени, то OOM

Page 73: A step-by-step approach toward high quality OutOfMemoryError analysis

73© 2016 NetCracker Technology Corporation Confidential

Чисто там, где не мусорят

• Java Flight Recorder / Java Mission Control

Page 74: A step-by-step approach toward high quality OutOfMemoryError analysis

74© 2016 NetCracker Technology Corporation Confidential

Как понять, кто создаёт объекты?

Java Flight Recorder• Позволяет узнать stack trace где создавались объекты• Позволяет узнать объём выделяемой памяти

Page 75: A step-by-step approach toward high quality OutOfMemoryError analysis

75© 2016 NetCracker Technology Corporation Confidential

Как понять, кто создаёт объекты?

Java Flight Recorder• Позволяет узнать stack trace где создавались объекты• Позволяет узнать объём выделяемой памяти• Бесплатно на test серверах

Page 76: A step-by-step approach toward high quality OutOfMemoryError analysis

76© 2016 NetCracker Technology Corporation Confidential

Как понять, кто создаёт объекты?

Java Flight Recorder• Позволяет узнать stack trace где создавались объекты• Позволяет узнать объём выделяемой памяти• Бесплатно на test серверах

Запуск:

• -XX:+UnlockCommercialFeatures -XX:+FlightRecorder-XX:FlightRecorderOptions=repository=jfr,defaultrecording=false

Page 77: A step-by-step approach toward high quality OutOfMemoryError analysis

77© 2016 NetCracker Technology Corporation Confidential

Как понять, кто создаёт объекты?

Java Flight Recorder• Позволяет узнать stack trace где создавались объекты• Позволяет узнать объём выделяемой памяти• Бесплатно на test серверах

Запуск:

• -XX:+UnlockCommercialFeatures -XX:+FlightRecorder-XX:FlightRecorderOptions=repository=jfr,defaultrecording=false

• jcmd <pid> JFR.start duration=2m filename=logs/myrecording.jfr settings=profile stackdepth=2000

Page 78: A step-by-step approach toward high quality OutOfMemoryError analysis

78© 2016 NetCracker Technology Corporation Confidential

OOM: heap space

Дамп памяти содержит снимок содержимого java heap• Как собрать: -XX:HeapDumpOnOutOfMemoryError

Page 79: A step-by-step approach toward high quality OutOfMemoryError analysis

79© 2016 NetCracker Technology Corporation Confidential

OOM: heap space

Дамп памяти содержит снимок содержимого java heap• Как собрать: -XX:HeapDumpOnOutOfMemoryError• jmap -dump

Page 80: A step-by-step approach toward high quality OutOfMemoryError analysis

80© 2016 NetCracker Technology Corporation Confidential

OOM: heap space

Дамп памяти содержит снимок содержимого java heap• Как собрать: -XX:HeapDumpOnOutOfMemoryError• jmap -dump• jmap -dump -F (force режим, если обычный не работает)

Page 81: A step-by-step approach toward high quality OutOfMemoryError analysis

81© 2016 NetCracker Technology Corporation Confidential

OOM: heap space

Дамп памяти содержит снимок содержимого java heap• Как собрать: -XX:HeapDumpOnOutOfMemoryError• jmap -dump• jmap -dump -F (force режим, если обычный не работает)• Чем смотреть: Eclipse Memory Analyzer, VisualVM, jol, jvm-tools

Page 82: A step-by-step approach toward high quality OutOfMemoryError analysis

82© 2016 NetCracker Technology Corporation Confidential

Page 83: A step-by-step approach toward high quality OutOfMemoryError analysis

83© 2016 NetCracker Technology Corporation Confidential

Скорость работы jmap

$jmap –dump .. real 0m7.992suser 0m0.304ssys 0m0.067s

$ jmap –dump –F ..real 24m4.378suser 21m56.321ssys 6m51.676s

Page 84: A step-by-step approach toward high quality OutOfMemoryError analysis

84© 2016 NetCracker Technology Corporation Confidential

В тяжёлых случаях

• core dump быстрее и надёжнее чем jmap -dump <pid>$ ulimit –ccore file size (blocks, -c) 33’222’111

Page 85: A step-by-step approach toward high quality OutOfMemoryError analysis

85© 2016 NetCracker Technology Corporation Confidential

В тяжёлых случаях

• core dump быстрее и надёжнее чем jmap -dump <pid>$ ulimit –ccore file size (blocks, -c) 33’222’111

• Из core dump можно получить hprof (через jmap …)

Page 86: A step-by-step approach toward high quality OutOfMemoryError analysis

86© 2016 NetCracker Technology Corporation Confidential

• Дамп памяти содержит данные всех объектов• Состояние потоков (thread dump)• Значения локальных переменных

Дампы памяти

Page 87: A step-by-step approach toward high quality OutOfMemoryError analysis

87© 2016 NetCracker Technology Corporation Confidential

• Дамп памяти содержит данные всех объектов• Состояние потоков (thread dump)• Значения локальных переменных

Дампы памяти

Да, пароли там тоже есть

Page 88: A step-by-step approach toward high quality OutOfMemoryError analysis

88© 2016 NetCracker Technology Corporation Confidential

• -Xmx2G, OracleJDK 1.8u60

java.lang.OutOfMemoryError: Java heap spaceDumping heap to java_pid59998.hprof ...Heap dump file created [1’650’484 bytes in 0.023 secs]Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

at Demo1.main(Demo1.java:6)

Маловато будет

Page 89: A step-by-step approach toward high quality OutOfMemoryError analysis

89© 2016 NetCracker Technology Corporation Confidential

• -Xmx2G, OracleJDK 1.8u60

java.lang.OutOfMemoryError: Java heap spaceDumping heap to java_pid59998.hprof ...Heap dump file created [1’650’484 bytes in 0.023 secs]Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

at Demo1.main(Demo1.java:6)

Маловато будет

long len = Runtime.getRuntime().maxMemory();long[] array = new long[(int) len]; Demo1.java:6

Page 90: A step-by-step approach toward high quality OutOfMemoryError analysis

90© 2016 NetCracker Technology Corporation Confidential

Терминология

«утекла память», «потребилась память»== кто-то мешает GC её освободить

Page 91: A step-by-step approach toward high quality OutOfMemoryError analysis

91© 2016 NetCracker Technology Corporation Confidential

Кто может держать память?

• Потоки (threads)

Page 92: A step-by-step approach toward high quality OutOfMemoryError analysis

92© 2016 NetCracker Technology Corporation Confidential

Кто может держать память?

• Потоки (threads)• Локальные переменные

Page 93: A step-by-step approach toward high quality OutOfMemoryError analysis

93© 2016 NetCracker Technology Corporation Confidential

Кто может держать память?

• Потоки (threads)• Локальные переменные• Кишки JVM

Page 94: A step-by-step approach toward high quality OutOfMemoryError analysis

94© 2016 NetCracker Technology Corporation Confidential

Кто может держать память?

• Потоки (threads)• Локальные переменные• Кишки JVM• И далее по цепочкам простых ссылок,

WeakReferences, SoftReferences, PhantomReferences

Page 95: A step-by-step approach toward high quality OutOfMemoryError analysis

95© 2016 NetCracker Technology Corporation Confidential

Кто может держать память?

• Потоки (threads)• Локальные переменные• Кишки JVM• И далее по цепочкам простых ссылок,

WeakReferences, SoftReferences, PhantomReferences, FinalReferences

‾√

Page 96: A step-by-step approach toward high quality OutOfMemoryError analysis

96© 2016 NetCracker Technology Corporation Confidential

‾√

WeakHashMap<K, V>

K1 V1

K2 V2

Page 97: A step-by-step approach toward high quality OutOfMemoryError analysis

97© 2016 NetCracker Technology Corporation Confidential

‾√

WeakHashMap<K, V>

K1 V1

K2 V2

Page 98: A step-by-step approach toward high quality OutOfMemoryError analysis

98© 2016 NetCracker Technology Corporation Confidential

‾√

WeakHashMap<K, V>

Page 99: A step-by-step approach toward high quality OutOfMemoryError analysis

99© 2016 NetCracker Technology Corporation Confidential

WeakHashMap<K, V>

K1 V1

K2 V2√‾

Page 100: A step-by-step approach toward high quality OutOfMemoryError analysis

100© 2016 NetCracker Technology Corporation Confidential

WeakHashMap<K, V>

K1 V1

K2 V2√‾

Page 101: A step-by-step approach toward high quality OutOfMemoryError analysis

101© 2016 NetCracker Technology Corporation Confidential

И освободится ли WeakHashMap<K, V>?

K1 V1

K2 V2?√‾

Page 102: A step-by-step approach toward high quality OutOfMemoryError analysis

102© 2016 NetCracker Technology Corporation Confidential

√‾

Освобождению не подлежит

K1 V1

K2 V2

Page 103: A step-by-step approach toward high quality OutOfMemoryError analysis

103© 2016 NetCracker Technology Corporation Confidential

√‾

Освобождению не подлежит

K1 V1

K2 V2

Page 104: A step-by-step approach toward high quality OutOfMemoryError analysis

104© 2016 NetCracker Technology Corporation Confidential

√‾

Освобождению не подлежит

K1 V1

K2 V2

Page 105: A step-by-step approach toward high quality OutOfMemoryError analysis

105© 2016 NetCracker Technology Corporation Confidential

√‾

Освобождению не подлежит

K1 V1

K2 V2

Page 106: A step-by-step approach toward high quality OutOfMemoryError analysis

106© 2016 NetCracker Technology Corporation Confidential

√‾

Освобождению не подлежит

K1 V1

K2 V2

Page 107: A step-by-step approach toward high quality OutOfMemoryError analysis

107© 2016 NetCracker Technology Corporation Confidential

√‾

Освобождению не подлежит

K1 V1

K2 V2

Page 108: A step-by-step approach toward high quality OutOfMemoryError analysis

108© 2016 NetCracker Technology Corporation Confidential

√‾

Освобождению не подлежит

K1 V1

K2 V2

Page 109: A step-by-step approach toward high quality OutOfMemoryError analysis

109© 2016 NetCracker Technology Corporation Confidential

И кто же так делает?

• XML element• Элемент хранит ссылку на документ, а тот на всё

остальное

Page 110: A step-by-step approach toward high quality OutOfMemoryError analysis

110© 2016 NetCracker Technology Corporation Confidential

И кто же так делает?

• XML element• Элемент хранит ссылку на документ, а тот на всё

остальное

• java.beans.…

Page 111: A step-by-step approach toward high quality OutOfMemoryError analysis

111© 2016 NetCracker Technology Corporation Confidential

Пример из жизни

• Запускаем Groovy

Page 112: A step-by-step approach toward high quality OutOfMemoryError analysis

112© 2016 NetCracker Technology Corporation Confidential

Пример из жизни

• Запускаем Groovy• Из JSR223 API (scripting API)

Page 113: A step-by-step approach toward high quality OutOfMemoryError analysis

113© 2016 NetCracker Technology Corporation Confidential

Пример из жизни

• Запускаем Groovy• Из JSR223 API (scripting API)• И получаем OutOfMemoryError

Page 114: A step-by-step approach toward high quality OutOfMemoryError analysis

114© 2016 NetCracker Technology Corporation Confidential

Терминология

Для любого объекта Ы есть 2 основных метрики• Shallow heap – объём памяти, занимаемый самим

объектом• Retained heap – объём памяти, который освободится,

если Ы окажется мусором

Page 115: A step-by-step approach toward high quality OutOfMemoryError analysis

115© 2016 NetCracker Technology Corporation Confidential

Dominator tree

2

3

4

5

№2 не доминирует №3

№4 доминирует №5

√‾

Page 116: A step-by-step approach toward high quality OutOfMemoryError analysis

116© 2016 NetCracker Technology Corporation Confidential

Groovy + Scripting for Java (JSR 223) = печаль (demo1)

Демо: groovy

Page 117: A step-by-step approach toward high quality OutOfMemoryError analysis

117© 2016 NetCracker Technology Corporation Confidential

Dominator Tree (demo1)• Показывает объекты, которые держат больше всего других

Page 118: A step-by-step approach toward high quality OutOfMemoryError analysis

118© 2016 NetCracker Technology Corporation Confidential

Разбираем строку в число

* http://shipilev.net/blog/2014/exceptional-performance

static long toLongFast(char[] c) throws IllegalArgumentException { if (c.length == 1) return c[0] - '0'; // Пусть с дробными разбираются другие throw new IllegalArgumentException(); *}

Page 119: A step-by-step approach toward high quality OutOfMemoryError analysis

119© 2016 NetCracker Technology Corporation Confidential

Так быстрее, но не утечёт ли память? static final IllegalArgumentException CFE = new IllegalArgumentException();

static long toLongFast(char[] c) throws IllegalArgumentException { if (c.length == 1) return c[0] - '0'; throw CFE;

Page 120: A step-by-step approach toward high quality OutOfMemoryError analysis

120© 2016 NetCracker Technology Corporation Confidential

Throwable наносит ответный удар

• StackTraceElement это сплошные строки, но в Throwable есть скрытое поле backtrace

Page 121: A step-by-step approach toward high quality OutOfMemoryError analysis

121© 2016 NetCracker Technology Corporation Confidential

Throwable наносит ответный удар

• StackTraceElement это сплошные строки, но в Throwable есть скрытое поле backtrace

• Оно прекрасно держит ссылки на классы из стектрейса

Page 122: A step-by-step approach toward high quality OutOfMemoryError analysis

122© 2016 NetCracker Technology Corporation Confidential

Throwable наносит ответный удар

• StackTraceElement это сплошные строки, но в Throwable есть скрытое поле backtrace

• Оно прекрасно держит ссылки на классы из стектрейса• Иногда это может быть неожиданной ссылкой на класс

Page 123: A step-by-step approach toward high quality OutOfMemoryError analysis

123© 2016 NetCracker Technology Corporation Confidential

Мораль

• Либо не используем «ControlFlowException»• Либо не заполняем stacktrace

static final IllegalArgumentException CFE = new IllegalArgumentException() { public Throwable fillInStackTrace() { return this; } }

Page 124: A step-by-step approach toward high quality OutOfMemoryError analysis

124© 2016 NetCracker Technology Corporation Confidential

Object#finalize

Не стоит использовать finalizer’ы для «освобождения ресурсов»

• Finalizable объекты живут на 1 цикл GC (падают в old gen, ужас-ужас)

Page 125: A step-by-step approach toward high quality OutOfMemoryError analysis

125© 2016 NetCracker Technology Corporation Confidential

Object#finalize

Не стоит использовать finalizer’ы для «освобождения ресурсов»

• Finalizable объекты живут на 1 цикл GC (падают в old gen, ужас-ужас)

• Невозможно объяснить JVM, что объект не надо финализировать (если вручную вызвали .close)

Page 126: A step-by-step approach toward high quality OutOfMemoryError analysis

126© 2016 NetCracker Technology Corporation Confidential

Object#finalize -> PhantomReference

PhantomReference позволяет организовать «автоматическое освобождение ресурсов» с поддержкой ручного:

• PhantomReference сохраняется в какую-нибудь map/set

Page 127: A step-by-step approach toward high quality OutOfMemoryError analysis

127© 2016 NetCracker Technology Corporation Confidential

Object#finalize -> PhantomReference

PhantomReference позволяет организовать «автоматическое освобождение ресурсов» с поддержкой ручного:

• PhantomReference сохраняется в какую-нибудь map/set

• Если объект выходит из видимости, GC обрабатывает Phantom

Page 128: A step-by-step approach toward high quality OutOfMemoryError analysis

128© 2016 NetCracker Technology Corporation Confidential

Object#finalize -> PhantomReference

PhantomReference позволяет организовать «автоматическое освобождение ресурсов» с поддержкой ручного:

• PhantomReference сохраняется в какую-нибудь map/set

• Если объект выходит из видимости, GC обрабатывает Phantom

• Если пользователь закрыл объект вручную, то там же и очищается Phantom

Page 129: A step-by-step approach toward high quality OutOfMemoryError analysis

129© 2016 NetCracker Technology Corporation Confidential

PhantomReference Map<Reference<Statement>, String> resources;ReferenceQueue<Statement> queue = new ReferenceQueue<>();

public void autoCleanup() throws Throwable { PreparedStatement ps = con.prepareStatement("select 1"); PhantomReference<Statement> ref = new PhantomReference<>(ps, queue); resources.put(ref, "name");

/* В методе .close(): */ ref.clear();}

Page 130: A step-by-step approach toward high quality OutOfMemoryError analysis

130© 2016 NetCracker Technology Corporation Confidential

На практике

• PostgreSQL JDBC драйвер pgjdbc использовал Statement#finalize

• @Benchmark на «создание statement» падал с OOM• После исключения finalize, стало 45ns/create даже

при 100% утекании (т.е. без ручных вызовов close):https://github.com/pgjdbc/pgjdbc/pull/299

Page 131: A step-by-step approach toward high quality OutOfMemoryError analysis

131© 2016 NetCracker Technology Corporation Confidential

• @shipilёv: не все хипдампы одинаково полезны

Eclipse Memory Analyzer

Page 132: A step-by-step approach toward high quality OutOfMemoryError analysis

132© 2016 NetCracker Technology Corporation Confidential

Puzzler

++i--Что это?

Page 133: A step-by-step approach toward high quality OutOfMemoryError analysis

133© 2016 NetCracker Technology Corporation Confidential

Puzzler

++i--^^^ оператор подёргивания

Page 134: A step-by-step approach toward high quality OutOfMemoryError analysis

134© 2014 NetCracker Technology Corporation Confidential

Демо

Page 135: A step-by-step approach toward high quality OutOfMemoryError analysis

135© 2016 NetCracker Technology Corporation Confidential

Dominator Tree

• Отображает то, сколько освободится, если удалить объект

Page 136: A step-by-step approach toward high quality OutOfMemoryError analysis

136© 2016 NetCracker Technology Corporation Confidential

Dominator Tree (demo2)

• Quiz: Может ли объект дважды попасть в Dominator Tree?

Page 137: A step-by-step approach toward high quality OutOfMemoryError analysis

137© 2016 NetCracker Technology Corporation Confidential

Основные окна Eclipse MAT (demo2)

• Class Histogram• Показывает суммарную информацию по классам

Page 138: A step-by-step approach toward high quality OutOfMemoryError analysis

138© 2016 NetCracker Technology Corporation Confidential

Dominator Tree (demo2)

• Как не погрязнуть в вечном разворачивании плюсиков?

Page 139: A step-by-step approach toward high quality OutOfMemoryError analysis

139© 2016 NetCracker Technology Corporation Confidential

Алгоритм анализа дампов в Eclipse MAT

• Retained Set• Immediate Dominators

Page 140: A step-by-step approach toward high quality OutOfMemoryError analysis

140© 2016 NetCracker Technology Corporation Confidential

Алгоритм анализа дампов в Eclipse MAT

• Dominator Tree• Retained Set• Immediate Dominators

Page 141: A step-by-step approach toward high quality OutOfMemoryError analysis

141© 2016 NetCracker Technology Corporation Confidential

Алгоритм анализа дампов в Eclipse MAT

• Dominator Tree• Retained Set• Immediate Dominators• Retained Set• Immediate Dominators• Retained Set

• Immediate Dominators

Page 142: A step-by-step approach toward high quality OutOfMemoryError analysis

142© 2016 NetCracker Technology Corporation Confidential

Dominator Tree

• “Show Retained Set” показывает плоский список удерживаемых объектов

Page 143: A step-by-step approach toward high quality OutOfMemoryError analysis

143© 2016 NetCracker Technology Corporation Confidential

Immediate dominators

• Кто-то очень любит HashMap$Entry. Как узнать кто?

• Immediate dominators!

Page 144: A step-by-step approach toward high quality OutOfMemoryError analysis

144© 2016 NetCracker Technology Corporation Confidential

HashMap$Entry

• Если очень захотеть, то можно сделать Map с накладными расходами в 4 байта на запись

Page 145: A step-by-step approach toward high quality OutOfMemoryError analysis

145© 2016 NetCracker Technology Corporation Confidential

HashMap$Entry

• Если очень захотеть, то можно сделать Map с накладными расходами в 4 байта на запись

• https://github.com/vlsi/compactmap• См. v8/design.html#prop_access

Page 146: A step-by-step approach toward high quality OutOfMemoryError analysis

146© 2016 NetCracker Technology Corporation Confidential

Но как же автоматизация?

• В Eclipse есть Object Query Language

Page 147: A step-by-step approach toward high quality OutOfMemoryError analysis

147© 2016 NetCracker Technology Corporation Confidential

Но как же автоматизация?

• В Eclipse есть Object Query Language• В простых случаях даже работает

Page 148: A step-by-step approach toward high quality OutOfMemoryError analysis

148© 2016 NetCracker Technology Corporation Confidential

Но как же автоматизация?

• В Eclipse есть ограниченный :( Object Query Language• Нет group by• Нет join• Нет distinct

Page 149: A step-by-step approach toward high quality OutOfMemoryError analysis

149© 2016 NetCracker Technology Corporation Confidential

OQL!

• В Eclipse есть ограниченный :( Object Query Language• Нет group by• Нет join• Нет distinct

• Может, оно и не нужно?

Page 150: A step-by-step approach toward high quality OutOfMemoryError analysis

150© 2016 NetCracker Technology Corporation Confidential

Примеры, когда OQL пасует

• Если в одной коллекции хранятся разнородные данные, то OQL не подходит• EJB bean cache• Свои кэши данных

• Если данные разбиты по разным java-объектам, то OQL не подходит

Page 151: A step-by-step approach toward high quality OutOfMemoryError analysis

151© 2016 NetCracker Technology Corporation Confidential

Ты ж программист

• Берём SQL engine: Apache Calcite

Page 152: A step-by-step approach toward high quality OutOfMemoryError analysis

152© 2016 NetCracker Technology Corporation Confidential

Ты ж программист

• Берём SQL engine: Apache Calcite• Прикручиваем его к MAT: mat-calcite-plugin

Page 153: A step-by-step approach toward high quality OutOfMemoryError analysis

153© 2016 NetCracker Technology Corporation Confidential

Ты ж программист

• Берём SQL engine: Apache Calcite• Прикручиваем его к MAT: mat-calcite-plugin• Получаем:

• JOIN, WHERE, GROUP BY, ORDER BY, HAVING• UNION, INTERSECT• Подзапросы• Аналитические функции (WINDOW, OVER)

Page 154: A step-by-step approach toward high quality OutOfMemoryError analysis

154© 2016 NetCracker Technology Corporation Confidential

Пример SQL

-- Tables:-- "java.lang.BigInteger" list of all BigIntegers-- "instanceof java.lang.BigInteger" BigIntegers and all

select u."@THIS", s."@RETAINED" from "java.lang.String" s , "java.net.URL" u where s."@THIS" = u.path

Page 155: A step-by-step approach toward high quality OutOfMemoryError analysis

155© 2016 NetCracker Technology Corporation Confidential

Mat-calcite-plugin

• Плюсы:• Хорошая поддержка SQL• Ставится из MAT (“install new software…”)

Page 156: A step-by-step approach toward high quality OutOfMemoryError analysis

156© 2016 NetCracker Technology Corporation Confidential

Mat-calcite-plugin

• Плюсы:• Хорошая поддержка SQL• Ставится из MAT (“install new software…”)

• Минусы:• Подходит не для каждого запроса: Calcite заточен

под full scan• Обход графа на SQL это та ещё радость

Page 157: A step-by-step approach toward high quality OutOfMemoryError analysis

157© 2016 NetCracker Technology Corporation Confidential

VisualVM

• VisualVM UI работает неторопливо, но OQL позволяет выполнять javascript map-reduce

• Распечатка System.properties:

select map(filter(heap.findClass('java.lang.System').props.table , 'it != null && it.key != null && it.value != null') , function (it) { var res = it.key.toString() + ' = ' + it.value.toString(); return res; });

Page 158: A step-by-step approach toward high quality OutOfMemoryError analysis

158© 2016 NetCracker Technology Corporation Confidential

aragozin/jvm-tools

• На очень больших дампах, dominator tree построить невозможно

• В таких случаях поможет HeapPath из состава aragozin/jvm-tools:• field1.field2.field3.*.field4• arrayField[0].arrayField2[*].field5• hashMap?entrySet[key=name].value

Page 159: A step-by-step approach toward high quality OutOfMemoryError analysis

159© 2016 NetCracker Technology Corporation Confidential

Ты ж java программист

• Java object layout хорошо подходит для анализа индивидуальных объектов:http://hg.openjdk.java.net/code-tools/jol/…/samples/

Page 160: A step-by-step approach toward high quality OutOfMemoryError analysis

160© 2016 NetCracker Technology Corporation Confidential

Ты ж java программист

• Java object layout хорошо подходит для анализа индивидуальных объектов:http://hg.openjdk.java.net/code-tools/jol/…/samples/

• Плюсы:• Управляется из java кода• Выдаёт точные значения

Page 161: A step-by-step approach toward high quality OutOfMemoryError analysis

161© 2016 NetCracker Technology Corporation Confidential

Ты ж java программист

• Java object layout хорошо подходит для анализа индивидуальных объектов:http://hg.openjdk.java.net/code-tools/jol/…/samples/

• Плюсы:• Управляется из java кода• Выдаёт точные значения

• Минусы:• Управляется из java кода

Page 162: A step-by-step approach toward high quality OutOfMemoryError analysis

162© 2016 NetCracker Technology Corporation Confidential

Выводы

• До OOM стараемся не доводить (-Xmx, thread pools)• Если довели, то снимаем хипдамп (jmap, coredump)• Обновляем JVM ради: исправления ошибок,

инструментария

Page 163: A step-by-step approach toward high quality OutOfMemoryError analysis

163© 2016 NetCracker Technology Corporation Confidential

• Владимир Ситников• Performance engineer @ NetCracker• [email protected]• @VladimirSitnikv

Спасибо

Page 164: A step-by-step approach toward high quality OutOfMemoryError analysis

Спасибо

164© 2015 NetCracker Technology Corporation Confidential