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

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

Embed Size (px)

Citation preview

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

© 2015 NetCracker Technology Corporation Confidential

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

Владимир СитниковJokerconf 2015

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

2© 2015 NetCracker Technology Corporation Confidential

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

Кто я

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

3© 2015 NetCracker Technology Corporation Confidential

О чём доклад

• Разбор некоторых OutOfMemoryError• Примеры подходов к анализу/защите от OOM• OpenJDK/OracleJDK

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

4© 2015 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: Разбор сложных случаев OutOfMemoryError

5© 2015 NetCracker Technology Corporation Confidential

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

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

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

6© 2015 NetCracker Technology Corporation Confidential

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

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

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

7© 2015 NetCracker Technology Corporation Confidential

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

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

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

8© 2015 NetCracker Technology Corporation Confidential

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

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

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

9© 2015 NetCracker Technology Corporation Confidential

OOMkiller

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

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

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

10© 2015 NetCracker Technology Corporation Confidential

OOMkiller

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

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

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

11© 2015 NetCracker Technology Corporation Confidential

OOMkiller

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

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

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

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

12© 2015 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 13: Разбор сложных случаев OutOfMemoryError

13© 2015 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 14: Разбор сложных случаев OutOfMemoryError

14© 2015 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: Разбор сложных случаев OutOfMemoryError

15© 2015 NetCracker Technology Corporation Confidential

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

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

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

16© 2015 NetCracker Technology Corporation Confidential

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

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

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

17© 2015 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 18: Разбор сложных случаев OutOfMemoryError

18© 2015 NetCracker Technology Corporation Confidential

NMT на практике

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

19© 2015 NetCracker Technology Corporation Confidential

Ценный мех NMT

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

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

20© 2015 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 21: Разбор сложных случаев OutOfMemoryError

21© 2015 NetCracker Technology Corporation Confidential

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

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

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

22© 2015 NetCracker Technology Corporation Confidential

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

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

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

23© 2015 NetCracker Technology Corporation Confidential

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

24© 2015 NetCracker Technology Corporation Confidential

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

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

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

25© 2015 NetCracker Technology Corporation Confidential

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

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

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

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

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

26© 2015 NetCracker Technology Corporation Confidential

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

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

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

27© 2015 NetCracker Technology Corporation Confidential

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

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

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

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

28© 2015 NetCracker Technology Corporation Confidential

OutOfMemoryError: unable to create native thread

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

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

29© 2015 NetCracker Technology Corporation Confidential

OutOfMemoryError: unable to create native thread

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

стека (thread native stack)

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

30© 2015 NetCracker Technology Corporation Confidential

OutOfMemoryError: unable to create native thread

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

стека (thread native stack)

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

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

31© 2015 NetCracker Technology Corporation Confidential

OutOfMemoryError: unable to create native thread

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

стека (thread native stack)

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

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

32© 2015 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 33: Разбор сложных случаев OutOfMemoryError

33© 2015 NetCracker Technology Corporation Confidential

limits

$ ulimit –a

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

34© 2015 NetCracker Technology Corporation Confidential

limits

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

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

35© 2015 NetCracker Technology Corporation Confidential

limits

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

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

36© 2015 NetCracker Technology Corporation Confidential

limits

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

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

37© 2015 NetCracker Technology Corporation Confidential

limits

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

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

38© 2015 NetCracker Technology Corporation Confidential

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

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

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

39© 2015 NetCracker Technology Corporation Confidential

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

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

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

40© 2015 NetCracker Technology Corporation Confidential

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

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

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

41© 2015 NetCracker Technology Corporation Confidential

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

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

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

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

42© 2015 NetCracker Technology Corporation Confidential

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

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

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

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

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

43© 2015 NetCracker Technology Corporation Confidential

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

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

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

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

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

44© 2015 NetCracker Technology Corporation Confidential

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

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

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

45© 2015 NetCracker Technology Corporation Confidential

Java heap

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

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

46© 2015 NetCracker Technology Corporation Confidential

Java heap

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

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

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

47© 2015 NetCracker Technology Corporation Confidential

Java heap

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

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

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

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

48© 2015 NetCracker Technology Corporation Confidential

OutOfMemoryError: PermGen space

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

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

49© 2015 NetCracker Technology Corporation Confidential

OutOfMemoryError: PermGen space

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

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

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

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

50© 2015 NetCracker Technology Corporation Confidential

OutOfMemoryError: PermGen space

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

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

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

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

51© 2015 NetCracker Technology Corporation Confidential

OutOfMemoryError: Java heap space

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

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

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

52© 2015 NetCracker Technology Corporation Confidential

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

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

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

53© 2015 NetCracker Technology Corporation Confidential

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

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

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

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

54© 2015 NetCracker Technology Corporation Confidential

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

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

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

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

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

55© 2015 NetCracker Technology Corporation Confidential

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

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

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

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

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

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

56© 2015 NetCracker Technology Corporation Confidential

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

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

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

57© 2015 NetCracker Technology Corporation Confidential

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

• Сплошные full gc

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

58© 2015 NetCracker Technology Corporation Confidential

Недоперепил

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

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

59© 2015 NetCracker Technology Corporation Confidential

Недоперепил

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

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

60© 2015 NetCracker Technology Corporation Confidential

Недоперепил

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

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

61© 2015 NetCracker Technology Corporation Confidential

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

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

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

62© 2015 NetCracker Technology Corporation Confidential

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

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

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

63© 2015 NetCracker Technology Corporation Confidential

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

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

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

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

64© 2015 NetCracker Technology Corporation Confidential

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

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

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

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

времени, то OOM

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

65© 2015 NetCracker Technology Corporation Confidential

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

• Java Flight Recorder / Java Mission Control

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

66© 2015 NetCracker Technology Corporation Confidential

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

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

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

67© 2015 NetCracker Technology Corporation Confidential

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

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

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

68© 2015 NetCracker Technology Corporation Confidential

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

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

Запуск:

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

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

69© 2015 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 70: Разбор сложных случаев OutOfMemoryError

70© 2015 NetCracker Technology Corporation Confidential

OOM: heap space

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

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

71© 2015 NetCracker Technology Corporation Confidential

OOM: heap space

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

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

72© 2015 NetCracker Technology Corporation Confidential

OOM: heap space

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

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

73© 2015 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 74: Разбор сложных случаев OutOfMemoryError

74© 2015 NetCracker Technology Corporation Confidential

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

75© 2015 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 76: Разбор сложных случаев OutOfMemoryError

76© 2015 NetCracker Technology Corporation Confidential

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

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

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

77© 2015 NetCracker Technology Corporation Confidential

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

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

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

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

78© 2015 NetCracker Technology Corporation Confidential

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

Дампы памяти

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

79© 2015 NetCracker Technology Corporation Confidential

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

Дампы памяти

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

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

80© 2015 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 81: Разбор сложных случаев OutOfMemoryError

81© 2015 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 82: Разбор сложных случаев OutOfMemoryError

82© 2015 NetCracker Technology Corporation Confidential

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

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

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

83© 2015 NetCracker Technology Corporation Confidential

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

• Потоки (threads)

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

84© 2015 NetCracker Technology Corporation Confidential

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

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

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

85© 2015 NetCracker Technology Corporation Confidential

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

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

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

86© 2015 NetCracker Technology Corporation Confidential

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

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

WeakReferences, SoftReferences, PhantomReferences

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

87© 2015 NetCracker Technology Corporation Confidential

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

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

WeakReferences, SoftReferences, PhantomReferences, FinalReferences

‾√

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

88© 2015 NetCracker Technology Corporation Confidential

‾√

WeakHashMap<K, V>

K1 V1

K2 V2

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

89© 2015 NetCracker Technology Corporation Confidential

‾√

WeakHashMap<K, V>

K1 V1

K2 V2

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

90© 2015 NetCracker Technology Corporation Confidential

‾√

WeakHashMap<K, V>

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

91© 2015 NetCracker Technology Corporation Confidential

WeakHashMap<K, V>

K1 V1

K2 V2√‾

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

92© 2015 NetCracker Technology Corporation Confidential

WeakHashMap<K, V>

K1 V1

K2 V2√‾

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

93© 2015 NetCracker Technology Corporation Confidential

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

K1 V1

K2 V2?√‾

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

94© 2015 NetCracker Technology Corporation Confidential

√‾

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

K1 V1

K2 V2

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

95© 2015 NetCracker Technology Corporation Confidential

√‾

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

K1 V1

K2 V2

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

96© 2015 NetCracker Technology Corporation Confidential

√‾

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

K1 V1

K2 V2

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

97© 2015 NetCracker Technology Corporation Confidential

√‾

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

K1 V1

K2 V2

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

98© 2015 NetCracker Technology Corporation Confidential

√‾

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

K1 V1

K2 V2

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

99© 2015 NetCracker Technology Corporation Confidential

√‾

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

K1 V1

K2 V2

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

100© 2015 NetCracker Technology Corporation Confidential

√‾

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

K1 V1

K2 V2

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

101© 2015 NetCracker Technology Corporation Confidential

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

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

остальное

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

102© 2015 NetCracker Technology Corporation Confidential

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

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

остальное

• java.beans.…

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

103© 2015 NetCracker Technology Corporation Confidential

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

• Запускаем Groovy

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

104© 2015 NetCracker Technology Corporation Confidential

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

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

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

105© 2015 NetCracker Technology Corporation Confidential

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

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

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

106© 2015 NetCracker Technology Corporation Confidential

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

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

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

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

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

107© 2015 NetCracker Technology Corporation Confidential

Dominator tree

2 3

4 5

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

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

√‾

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

108© 2015 NetCracker Technology Corporation Confidential

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

Демо: groovy

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

109© 2015 NetCracker Technology Corporation Confidential

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

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

110© 2015 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 111: Разбор сложных случаев OutOfMemoryError

111© 2015 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 112: Разбор сложных случаев OutOfMemoryError

112© 2015 NetCracker Technology Corporation Confidential

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

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

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

113© 2015 NetCracker Technology Corporation Confidential

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

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

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

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

114© 2015 NetCracker Technology Corporation Confidential

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

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

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

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

115© 2015 NetCracker Technology Corporation Confidential

Мораль

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

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

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

116© 2015 NetCracker Technology Corporation Confidential

Object#finalize

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

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

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

117© 2015 NetCracker Technology Corporation Confidential

Object#finalize

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

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

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

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

118© 2015 NetCracker Technology Corporation Confidential

Object#finalize -> PhantomReference

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

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

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

119© 2015 NetCracker Technology Corporation Confidential

Object#finalize -> PhantomReference

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

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

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

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

120© 2015 NetCracker Technology Corporation Confidential

Object#finalize -> PhantomReference

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

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

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

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

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

121© 2015 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 122: Разбор сложных случаев OutOfMemoryError

122© 2015 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 123: Разбор сложных случаев OutOfMemoryError

123© 2015 NetCracker Technology Corporation Confidential

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

Eclipse Memory Analyzer

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

124© 2015 NetCracker Technology Corporation Confidential

Puzzler

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

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

125© 2015 NetCracker Technology Corporation Confidential

Puzzler

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

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

126© 2014 NetCracker Technology Corporation Confidential

Демо

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

127© 2015 NetCracker Technology Corporation Confidential

Dominator Tree (demo2)

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

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

128© 2015 NetCracker Technology Corporation Confidential

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

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

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

129© 2015 NetCracker Technology Corporation Confidential

Dominator Tree (demo2)

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

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

130© 2015 NetCracker Technology Corporation Confidential

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

• Retained Set• Immediate Dominators

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

131© 2015 NetCracker Technology Corporation Confidential

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

• Dominator Tree• Retained Set• Immediate Dominators

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

132© 2015 NetCracker Technology Corporation Confidential

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

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

• Immediate Dominators

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

133© 2015 NetCracker Technology Corporation Confidential

Dominator Tree

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

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

134© 2015 NetCracker Technology Corporation Confidential

Immediate dominators

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

• Immediate dominators!

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

135© 2015 NetCracker Technology Corporation Confidential

HashMap$Entry

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

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

136© 2015 NetCracker Technology Corporation Confidential

HashMap

HashMap Entry[]

Entryid

41

Entryname

qwe

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

137© 2015 NetCracker Technology Corporation Confidential

HashMap: entry лишние

HashMap Entry[]

Entryid

41

Entryname

qwe

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

138© 2015 NetCracker Technology Corporation Confidential

HashMap

HashMap Entry[]

Entryid

41

Entryname

qwe

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

139© 2015 NetCracker Technology Corporation Confidential

CompactMap

CMap1 Object[]41

qwe

CMap2

keyposid=0

name=1

Object[]42

rty

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

140© 2015 NetCracker Technology Corporation Confidential

HashMap$Entry

• Работает, если форма (состав ключей) у многих объектов одинаковая• Например, у всех объектов есть запись “width”=“100%”

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

141© 2015 NetCracker Technology Corporation Confidential

HashMap$Entry

• Работает, если форма (состав ключей) у многих объектов одинаковая• Например, у всех объектов есть запись “width”=“100%”

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

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

142© 2015 NetCracker Technology Corporation Confidential

CompactHashMap

HashMap -> CompactHashMap в реальном проекте:

• 500МиБ –> 290МиБ• 3.0 сек / 1M обращений -> 150 сек / 1M обращений

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

143© 2015 NetCracker Technology Corporation Confidential

CompactHashMap

HashMap -> CompactHashMap в реальном проекте:

• 500МиБ –> 290МиБ• 3.0 сек / 1M обращений -> 150 сек / 1M обращений

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

144© 2015 NetCracker Technology Corporation Confidential

ReservedCodeCacheSize

• Если у JIT компилятора заканчивается память, то он перестаёт компилировать

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

145© 2015 NetCracker Technology Corporation Confidential

ReservedCodeCacheSize

• Если у JIT компилятора заканчивается память, то он перестаёт компилировать

• В Weblogic/EE/… стандартных 64M мало

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

146© 2015 NetCracker Technology Corporation Confidential

ReservedCodeCacheSize

• Если у JIT компилятора заканчивается память, то он перестаёт компилировать

• В Weblogic/EE/… стандартных 64M мало• -XX:+ReservedCodeCacheSize=128m/192m

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

147© 2015 NetCracker Technology Corporation Confidential

CompactHashMap

HashMap -> CompactHashMap, -XX:+ReservedCodeCacheSize=128m:

• 500МиБ –> 290МиБ• 3.0 сек / 1M обращений -> 3.5 сек / 1M обращений

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

148© 2015 NetCracker Technology Corporation Confidential

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

• В Eclipse есть Object Query Language

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

149© 2015 NetCracker Technology Corporation Confidential

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

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

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

150© 2015 NetCracker Technology Corporation Confidential

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

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

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

151© 2015 NetCracker Technology Corporation Confidential

OQL!

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

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

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

152© 2015 NetCracker Technology Corporation Confidential

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

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

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

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

153© 2015 NetCracker Technology Corporation Confidential

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

• Берём SQL engine: Apache Calcite

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

154© 2015 NetCracker Technology Corporation Confidential

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

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

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

155© 2015 NetCracker Technology Corporation Confidential

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

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

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

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

156© 2015 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 157: Разбор сложных случаев OutOfMemoryError

157© 2015 NetCracker Technology Corporation Confidential

Mat-calcite-plugin

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

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

158© 2015 NetCracker Technology Corporation Confidential

Mat-calcite-plugin

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

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

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

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

159© 2015 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 160: Разбор сложных случаев OutOfMemoryError

160© 2015 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 161: Разбор сложных случаев OutOfMemoryError

161© 2015 NetCracker Technology Corporation Confidential

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

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

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

162© 2015 NetCracker Technology Corporation Confidential

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

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

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

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

163© 2015 NetCracker Technology Corporation Confidential

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

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

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

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

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

164© 2015 NetCracker Technology Corporation Confidential

Выводы

• До OOM стараемся не доводить (-Xmx, thread pools, и т.п.)

• Если довели, то снимаем хипдамп (jmap, coredump)

• Обновляем JVM ради: исправления ошибок, инструментария

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

165© 2015 NetCracker Technology Corporation Confidential

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

Спасибо

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

Спасибо

166© 2015 NetCracker Technology Corporation Confidential