Post on 07-Jan-2017
© 2016 NetCracker Technology Corporation Confidential
Разбор сложных случаев OutOfMemoryError
Владимир СитниковJEEConf 2016
2© 2016 NetCracker Technology Corporation Confidential
• Владимир Ситников• Performance engineer @ NetCracker• sitnikov@netcracker.com• @VladimirSitnikv
Кто я
3© 2016 NetCracker Technology Corporation Confidential
О чём доклад
• Разбор некоторых out of memory: OS, JVM• Примеры подходов к анализу/защите от OOM• OpenJDK/OracleJDK
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• ...
5© 2016 NetCracker Technology Corporation Confidential
Дело о потерянном процессе
• Java процесс работал и пропал
6© 2016 NetCracker Technology Corporation Confidential
Дело о потерянном процессе
• Java процесс работал и пропал• hs_err файл не появился
7© 2016 NetCracker Technology Corporation Confidential
Дело о потерянном процессе
• Java процесс работал и пропал• hs_err файл не появился• В out, err, log пусто
8© 2016 NetCracker Technology Corporation Confidential
Дело о потерянном процессе
• Java процесс работал и пропал• hs_err файл не появился• В out, err, log пусто• Как так?
9© 2016 NetCracker Technology Corporation Confidential
OOMkiller
У Linux память конечна, и если она заканчивается, то может случиться разное:
• умрёт невезучий процесс (по умолчанию)
10© 2016 NetCracker Technology Corporation Confidential
OOMkiller
У Linux память конечна, и если она заканчивается, то может случиться разное:
• умрёт невезучий процесс (по умолчанию)• malloc вернёт ошибку «нет памяти»
11© 2016 NetCracker Technology Corporation Confidential
OOMkiller
У Linux память конечна, и если она заканчивается, то может случиться разное:
• умрёт невезучий процесс (по умолчанию)• malloc вернёт ошибку «нет памяти»
Ключевое слово в Linux: vm.overcommit_memory=0
12© 2016 NetCracker Technology Corporation Confidential
vm.overcommit_memory=0
vm.overcommit_memory=0• Выглядит хорошо (не будет overcommit)
13© 2016 NetCracker Technology Corporation Confidential
vm.overcommit_memory=0
vm.overcommit_memory=0• Выглядит хорошо (не будет overcommit)• Работает не всегда: многие процессы выделяют,
но не используют память (~fork syscall)
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
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
Занимаемая память
Свободная память
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
17© 2016 NetCracker Technology Corporation Confidential
Следим за native памятью
• -XX:+NativeMemoryTracking=[off|summary|detail]
18© 2016 NetCracker Technology Corporation Confidential
Следим за native памятью
• -XX:+NativeMemoryTracking=[off|summary|detail]• Работает начиная с 1.7u40
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
20© 2016 NetCracker Technology Corporation Confidential
NMT на практике
21© 2016 NetCracker Technology Corporation Confidential
Ценный мех NMT
NMT позволяет• более адресно заводить тикеты на OpenJDK• проверять наличие утечек «служебной» памятиПример: GROOVY-7498 Groovy native memory leak
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
23© 2016 NetCracker Technology Corporation Confidential
Запускаем процесс
new ProcessBuilder("ping","123.321.123.321") .start();
24© 2016 NetCracker Technology Corporation Confidential
Запускаем процесс
new ProcessBuilder("ping", "8.8.8.8") .start();
25© 2016 NetCracker Technology Corporation Confidential
26© 2016 NetCracker Technology Corporation Confidential
На самом деле, можно
Если версия JDK свежая, то проблем нет:• https://bugs.openjdk.java.net/browse/JDK-5049299• 1.7u60+ всё ок• 1.8u??+ (в 8u60 исправление есть наверняка)
27© 2016 NetCracker Technology Corporation Confidential
В предыдущих серияхверсиях
• ProcessBuilder#start() использует fork()
• -Xmx8g «по наследству» передаётся в ping• В итоге ping либо не запустится, либо есть
шанс разбудить oomkiller
28© 2016 NetCracker Technology Corporation Confidential
Как запускать процессы в OpenJDK<1.7u60
• Либо вообще не запускать процессы
29© 2016 NetCracker Technology Corporation Confidential
Как запускать процессы в OpenJDK<1.7u60
• Либо вообще не запускать процессы• Либо использовать jnr-posix (напрямую или из JRuby)
• https://github.com/jnr/jnr-posix
30© 2016 NetCracker Technology Corporation Confidential
OutOfMemoryError: unable to create native thread
• Кто виноват?
31© 2016 NetCracker Technology Corporation Confidential
OutOfMemoryError: unable to create native thread
• Кто виноват?• 32bit JVM и в адресном пространстве уже негде выделить место
для стека (thread native stack)
32© 2016 NetCracker Technology Corporation Confidential
OutOfMemoryError: unable to create native thread
• Кто виноват?• 32bit JVM и в адресном пространстве уже негде выделить
место для стека (thread native stack)
• Что делать?• Переходить на 64bit JVM
33© 2016 NetCracker Technology Corporation Confidential
OutOfMemoryError: unable to create native thread
• Кто виноват?• 32bit JVM и в адресном пространстве уже негде выделить
место для стека (thread native stack)
• Что делать?• Переходить на 64bit JVM• Или уменьшать -XX:ThreadStackSize, уменьшать -
XX:MaxPermSize
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)
35© 2016 NetCracker Technology Corporation Confidential
limits
$ ulimit –a
36© 2016 NetCracker Technology Corporation Confidential
limits
$ ulimit –avirtual memory (kbytes, -v) unlimited
37© 2016 NetCracker Technology Corporation Confidential
limits
$ ulimit –avirtual memory (kbytes, -v) unlimitedopen files (-n) 16384
38© 2016 NetCracker Technology Corporation Confidential
limits
$ ulimit –avirtual memory (kbytes, -v) unlimitedopen files (-n) 16384max user processes (-u) 100000
39© 2016 NetCracker Technology Corporation Confidential
limits
$ ulimit –avirtual memory (kbytes, -v) unlimitedopen files (-n) 16384max user processes (-u) 100000stack size (kbytes, -s) 10240
40© 2016 NetCracker Technology Corporation Confidential
Действия в случае OutOfMemoryError
try { "основной_монитор".notifyAll();} catch (OutOfMemoryError e) { log.info("Нужно больше памяти", e);}
41© 2016 NetCracker Technology Corporation Confidential
Действия в случае OutOfMemoryError
try { "основной_монитор".notifyAll();} catch (OutOfMemoryError e) { log.info("Нужно больше памяти", e);}
42© 2016 NetCracker Technology Corporation Confidential
Реальные проблемы
• OOM может получить любой поток в любой момент времени
43© 2016 NetCracker Technology Corporation Confidential
Реальные проблемы
• OOM может получить любой поток в любой момент времени
• Например, ReentrantLock в момент unlock
44© 2016 NetCracker Technology Corporation Confidential
Реальные проблемы
• OOM может получить любой поток в любой момент времени
• Например, ReentrantLock в момент unlock
• И мы получим вечнозанятую блокировку, сломанную ArrayBlockingQueue, …
45© 2016 NetCracker Technology Corporation Confidential
Реальные проблемы
• OOM может получить любой поток в любой момент времени
• Например, ReentrantLock в момент unlock• И мы получим вечнозанятую блокировку,
сломанную ArrayBlockingQueue, …• Аналогично и в случае StackOverflowError
46© 2016 NetCracker Technology Corporation Confidential
В случае аварии
В случае OutOfMemoryError/StackOverflowError гораздо правильнее делать так:• System.exit(146)• -XX:OnError="kill -9 %p"
47© 2016 NetCracker Technology Corporation Confidential
Реальные проблемы
• Но как же ReentrantLock?
48© 2016 NetCracker Technology Corporation Confidential
Реальные проблемы
• Но как же ReentrantLock?• JEP 270: Reserved Stack Areas for Critical Sections
доработка включена в JDK9
49© 2016 NetCracker Technology Corporation Confidential
В случае аварии
В случае OutOfMemoryError/StackOverflowError гораздо правильнее делать так:• java 1.8u92+: JDK-8138745
-XX:+ExitOnOutOfMemory-XX:+CrashOnOutOfMemory
50© 2016 NetCracker Technology Corporation Confidential
Java heap
• Хранит java объекты, их содержимое
51© 2016 NetCracker Technology Corporation Confidential
Java heap
• Хранит java объекты, их содержимое
• Очищается сборщиком мусора
52© 2016 NetCracker Technology Corporation Confidential
Java heap
• Хранит java объекты, их содержимое
• Очищается сборщиком мусора
• Бывает, заканчивается
53© 2016 NetCracker Technology Corporation Confidential
OutOfMemoryError: PermGen space
• Кто виноват?• Размер PermGen слишком мал• Загружено слишком много классов
54© 2016 NetCracker Technology Corporation Confidential
OutOfMemoryError: PermGen space
• Кто виноват?• Размер PermGen слишком мал• Загружено слишком много классов
• Что делать?• Увеличивать perm gen: -XX:PermSize=512M -XX:MaxPermSize=512M
• Искать лишние классы: jmap –histo
55© 2016 NetCracker Technology Corporation Confidential
OutOfMemoryError: PermGen space
• Кто виноват?• Размер PermGen слишком мал• Загружено слишком много классов
• Что делать?• Увеличивать perm gen: -XX:PermSize=512M -XX:MaxPermSize=512M
• Искать лишние классы: jmap –histo• Обновлять java (в 8-ке будет ошибка Metadata space:)
56© 2016 NetCracker Technology Corporation Confidential
OutOfMemoryError: Java heap space
• Кто виноват?• Выделено мало памяти• Garbage Collector не успел собрать мусор
• Что делать?• Выделять больше памяти: -Xms, -Xmx• Анализировать использование памяти
57© 2016 NetCracker Technology Corporation Confidential
Как анализировать занятость heap
GC log фиксирует приход-расход памяти по времени
58© 2016 NetCracker Technology Corporation Confidential
Как анализировать занятость heap
GC log фиксирует приход-расход памяти по времени
• Как собрать: -Xloggc:logs/gc.log, -XX:+PrintGCDetails, и т.д.
59© 2016 NetCracker Technology Corporation Confidential
Как анализировать занятость heap
GC log фиксирует приход-расход памяти по времени
• Как собрать: -Xloggc:logs/gc.log, -XX:+PrintGCDetails, и т.д.
• Чем смотреть: GCViewer
60© 2016 NetCracker Technology Corporation Confidential
Как анализировать занятость heap
GC log фиксирует приход-расход памяти по времени
• Как собрать: -Xloggc:logs/gc.log, -XX:+PrintGCDetails, и т.д.
• Чем смотреть: GCViewer
• На что смотреть: «занятость памяти после full gc»
61© 2016 NetCracker Technology Corporation Confidential
GC лог здорового человека
• 60мс minor, 3sec major паузы
62© 2016 NetCracker Technology Corporation Confidential
GC лог здорового человека
• 60мс minor, 3sec major паузы
63© 2016 NetCracker Technology Corporation Confidential
GC лог здорового человека
• 60мс minor, 3sec major паузы
64© 2016 NetCracker Technology Corporation Confidential
GC лог курильщика
• Сплошные full gc
65© 2016 NetCracker Technology Corporation Confidential
GC лог курильщика
• Сплошные full gc
66© 2016 NetCracker Technology Corporation Confidential
Недоперепил
• Бывает, памяти остаётся мало• GC постоянно как-то находит крохи мусора
67© 2016 NetCracker Technology Corporation Confidential
Недоперепил
• Бывает, памяти остаётся мало• GC постоянно как-то находит крохи мусора• А OutOfMemory всё нет и нет!
68© 2016 NetCracker Technology Corporation Confidential
Недоперепил
• Бывает, памяти остаётся мало• GC постоянно как-то находит крохи мусора• А OutOfMemory всё нет и нет!• Что делать, шеф?
69© 2016 NetCracker Technology Corporation Confidential
Варианты действий, когда почти OOM
• Jmap – снимать дамп вручную
70© 2016 NetCracker Technology Corporation Confidential
Варианты действий, когда почти OOM
• Jmap – снимать дамп вручную• GC overhead limit
71© 2016 NetCracker Technology Corporation Confidential
Варианты действий, когда почти OOM
• Jmap – снимать дамп вручную• GC overhead limit
• -XX:GCHeapFreeLimit=20 (2 по умолчанию)‒ Если после full GC останется меньше X%, то OOM
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
73© 2016 NetCracker Technology Corporation Confidential
Чисто там, где не мусорят
• Java Flight Recorder / Java Mission Control
74© 2016 NetCracker Technology Corporation Confidential
Как понять, кто создаёт объекты?
Java Flight Recorder• Позволяет узнать stack trace где создавались объекты• Позволяет узнать объём выделяемой памяти
75© 2016 NetCracker Technology Corporation Confidential
Как понять, кто создаёт объекты?
Java Flight Recorder• Позволяет узнать stack trace где создавались объекты• Позволяет узнать объём выделяемой памяти• Бесплатно на test серверах
76© 2016 NetCracker Technology Corporation Confidential
Как понять, кто создаёт объекты?
Java Flight Recorder• Позволяет узнать stack trace где создавались объекты• Позволяет узнать объём выделяемой памяти• Бесплатно на test серверах
Запуск:
• -XX:+UnlockCommercialFeatures -XX:+FlightRecorder-XX:FlightRecorderOptions=repository=jfr,defaultrecording=false
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
78© 2016 NetCracker Technology Corporation Confidential
OOM: heap space
Дамп памяти содержит снимок содержимого java heap• Как собрать: -XX:HeapDumpOnOutOfMemoryError
79© 2016 NetCracker Technology Corporation Confidential
OOM: heap space
Дамп памяти содержит снимок содержимого java heap• Как собрать: -XX:HeapDumpOnOutOfMemoryError• jmap -dump
80© 2016 NetCracker Technology Corporation Confidential
OOM: heap space
Дамп памяти содержит снимок содержимого java heap• Как собрать: -XX:HeapDumpOnOutOfMemoryError• jmap -dump• jmap -dump -F (force режим, если обычный не работает)
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
82© 2016 NetCracker Technology Corporation Confidential
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
84© 2016 NetCracker Technology Corporation Confidential
В тяжёлых случаях
• core dump быстрее и надёжнее чем jmap -dump <pid>$ ulimit –ccore file size (blocks, -c) 33’222’111
85© 2016 NetCracker Technology Corporation Confidential
В тяжёлых случаях
• core dump быстрее и надёжнее чем jmap -dump <pid>$ ulimit –ccore file size (blocks, -c) 33’222’111
• Из core dump можно получить hprof (через jmap …)
86© 2016 NetCracker Technology Corporation Confidential
• Дамп памяти содержит данные всех объектов• Состояние потоков (thread dump)• Значения локальных переменных
Дампы памяти
87© 2016 NetCracker Technology Corporation Confidential
• Дамп памяти содержит данные всех объектов• Состояние потоков (thread dump)• Значения локальных переменных
Дампы памяти
Да, пароли там тоже есть
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)
Маловато будет
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
90© 2016 NetCracker Technology Corporation Confidential
Терминология
«утекла память», «потребилась память»== кто-то мешает GC её освободить
91© 2016 NetCracker Technology Corporation Confidential
Кто может держать память?
• Потоки (threads)
92© 2016 NetCracker Technology Corporation Confidential
Кто может держать память?
• Потоки (threads)• Локальные переменные
93© 2016 NetCracker Technology Corporation Confidential
Кто может держать память?
• Потоки (threads)• Локальные переменные• Кишки JVM
94© 2016 NetCracker Technology Corporation Confidential
Кто может держать память?
• Потоки (threads)• Локальные переменные• Кишки JVM• И далее по цепочкам простых ссылок,
WeakReferences, SoftReferences, PhantomReferences
95© 2016 NetCracker Technology Corporation Confidential
Кто может держать память?
• Потоки (threads)• Локальные переменные• Кишки JVM• И далее по цепочкам простых ссылок,
WeakReferences, SoftReferences, PhantomReferences, FinalReferences
‾√
96© 2016 NetCracker Technology Corporation Confidential
‾√
WeakHashMap<K, V>
K1 V1
K2 V2
97© 2016 NetCracker Technology Corporation Confidential
‾√
WeakHashMap<K, V>
K1 V1
K2 V2
98© 2016 NetCracker Technology Corporation Confidential
‾√
WeakHashMap<K, V>
99© 2016 NetCracker Technology Corporation Confidential
WeakHashMap<K, V>
K1 V1
K2 V2√‾
100© 2016 NetCracker Technology Corporation Confidential
WeakHashMap<K, V>
K1 V1
K2 V2√‾
101© 2016 NetCracker Technology Corporation Confidential
И освободится ли WeakHashMap<K, V>?
K1 V1
K2 V2?√‾
102© 2016 NetCracker Technology Corporation Confidential
√‾
Освобождению не подлежит
K1 V1
K2 V2
103© 2016 NetCracker Technology Corporation Confidential
√‾
Освобождению не подлежит
K1 V1
K2 V2
104© 2016 NetCracker Technology Corporation Confidential
√‾
Освобождению не подлежит
K1 V1
K2 V2
105© 2016 NetCracker Technology Corporation Confidential
√‾
Освобождению не подлежит
K1 V1
K2 V2
106© 2016 NetCracker Technology Corporation Confidential
√‾
Освобождению не подлежит
K1 V1
K2 V2
107© 2016 NetCracker Technology Corporation Confidential
√‾
Освобождению не подлежит
K1 V1
K2 V2
108© 2016 NetCracker Technology Corporation Confidential
√‾
Освобождению не подлежит
K1 V1
K2 V2
109© 2016 NetCracker Technology Corporation Confidential
И кто же так делает?
• XML element• Элемент хранит ссылку на документ, а тот на всё
остальное
110© 2016 NetCracker Technology Corporation Confidential
И кто же так делает?
• XML element• Элемент хранит ссылку на документ, а тот на всё
остальное
• java.beans.…
111© 2016 NetCracker Technology Corporation Confidential
Пример из жизни
• Запускаем Groovy
112© 2016 NetCracker Technology Corporation Confidential
Пример из жизни
• Запускаем Groovy• Из JSR223 API (scripting API)
113© 2016 NetCracker Technology Corporation Confidential
Пример из жизни
• Запускаем Groovy• Из JSR223 API (scripting API)• И получаем OutOfMemoryError
114© 2016 NetCracker Technology Corporation Confidential
Терминология
Для любого объекта Ы есть 2 основных метрики• Shallow heap – объём памяти, занимаемый самим
объектом• Retained heap – объём памяти, который освободится,
если Ы окажется мусором
115© 2016 NetCracker Technology Corporation Confidential
Dominator tree
2
3
4
5
№2 не доминирует №3
№4 доминирует №5
√‾
116© 2016 NetCracker Technology Corporation Confidential
Groovy + Scripting for Java (JSR 223) = печаль (demo1)
Демо: groovy
117© 2016 NetCracker Technology Corporation Confidential
Dominator Tree (demo1)• Показывает объекты, которые держат больше всего других
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(); *}
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;
120© 2016 NetCracker Technology Corporation Confidential
Throwable наносит ответный удар
• StackTraceElement это сплошные строки, но в Throwable есть скрытое поле backtrace
121© 2016 NetCracker Technology Corporation Confidential
Throwable наносит ответный удар
• StackTraceElement это сплошные строки, но в Throwable есть скрытое поле backtrace
• Оно прекрасно держит ссылки на классы из стектрейса
122© 2016 NetCracker Technology Corporation Confidential
Throwable наносит ответный удар
• StackTraceElement это сплошные строки, но в Throwable есть скрытое поле backtrace
• Оно прекрасно держит ссылки на классы из стектрейса• Иногда это может быть неожиданной ссылкой на класс
123© 2016 NetCracker Technology Corporation Confidential
Мораль
• Либо не используем «ControlFlowException»• Либо не заполняем stacktrace
static final IllegalArgumentException CFE = new IllegalArgumentException() { public Throwable fillInStackTrace() { return this; } }
124© 2016 NetCracker Technology Corporation Confidential
Object#finalize
Не стоит использовать finalizer’ы для «освобождения ресурсов»
• Finalizable объекты живут на 1 цикл GC (падают в old gen, ужас-ужас)
125© 2016 NetCracker Technology Corporation Confidential
Object#finalize
Не стоит использовать finalizer’ы для «освобождения ресурсов»
• Finalizable объекты живут на 1 цикл GC (падают в old gen, ужас-ужас)
• Невозможно объяснить JVM, что объект не надо финализировать (если вручную вызвали .close)
126© 2016 NetCracker Technology Corporation Confidential
Object#finalize -> PhantomReference
PhantomReference позволяет организовать «автоматическое освобождение ресурсов» с поддержкой ручного:
• PhantomReference сохраняется в какую-нибудь map/set
127© 2016 NetCracker Technology Corporation Confidential
Object#finalize -> PhantomReference
PhantomReference позволяет организовать «автоматическое освобождение ресурсов» с поддержкой ручного:
• PhantomReference сохраняется в какую-нибудь map/set
• Если объект выходит из видимости, GC обрабатывает Phantom
128© 2016 NetCracker Technology Corporation Confidential
Object#finalize -> PhantomReference
PhantomReference позволяет организовать «автоматическое освобождение ресурсов» с поддержкой ручного:
• PhantomReference сохраняется в какую-нибудь map/set
• Если объект выходит из видимости, GC обрабатывает Phantom
• Если пользователь закрыл объект вручную, то там же и очищается Phantom
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();}
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
131© 2016 NetCracker Technology Corporation Confidential
• @shipilёv: не все хипдампы одинаково полезны
Eclipse Memory Analyzer
132© 2016 NetCracker Technology Corporation Confidential
Puzzler
++i--Что это?
133© 2016 NetCracker Technology Corporation Confidential
Puzzler
++i--^^^ оператор подёргивания
134© 2014 NetCracker Technology Corporation Confidential
Демо
135© 2016 NetCracker Technology Corporation Confidential
Dominator Tree
• Отображает то, сколько освободится, если удалить объект
136© 2016 NetCracker Technology Corporation Confidential
Dominator Tree (demo2)
• Quiz: Может ли объект дважды попасть в Dominator Tree?
137© 2016 NetCracker Technology Corporation Confidential
Основные окна Eclipse MAT (demo2)
• Class Histogram• Показывает суммарную информацию по классам
138© 2016 NetCracker Technology Corporation Confidential
Dominator Tree (demo2)
• Как не погрязнуть в вечном разворачивании плюсиков?
139© 2016 NetCracker Technology Corporation Confidential
Алгоритм анализа дампов в Eclipse MAT
• Retained Set• Immediate Dominators
140© 2016 NetCracker Technology Corporation Confidential
Алгоритм анализа дампов в Eclipse MAT
• Dominator Tree• Retained Set• Immediate Dominators
141© 2016 NetCracker Technology Corporation Confidential
Алгоритм анализа дампов в Eclipse MAT
• Dominator Tree• Retained Set• Immediate Dominators• Retained Set• Immediate Dominators• Retained Set
• Immediate Dominators
142© 2016 NetCracker Technology Corporation Confidential
Dominator Tree
• “Show Retained Set” показывает плоский список удерживаемых объектов
143© 2016 NetCracker Technology Corporation Confidential
Immediate dominators
• Кто-то очень любит HashMap$Entry. Как узнать кто?
• Immediate dominators!
144© 2016 NetCracker Technology Corporation Confidential
HashMap$Entry
• Если очень захотеть, то можно сделать Map с накладными расходами в 4 байта на запись
145© 2016 NetCracker Technology Corporation Confidential
HashMap$Entry
• Если очень захотеть, то можно сделать Map с накладными расходами в 4 байта на запись
• https://github.com/vlsi/compactmap• См. v8/design.html#prop_access
146© 2016 NetCracker Technology Corporation Confidential
Но как же автоматизация?
• В Eclipse есть Object Query Language
147© 2016 NetCracker Technology Corporation Confidential
Но как же автоматизация?
• В Eclipse есть Object Query Language• В простых случаях даже работает
148© 2016 NetCracker Technology Corporation Confidential
Но как же автоматизация?
• В Eclipse есть ограниченный :( Object Query Language• Нет group by• Нет join• Нет distinct
149© 2016 NetCracker Technology Corporation Confidential
OQL!
• В Eclipse есть ограниченный :( Object Query Language• Нет group by• Нет join• Нет distinct
• Может, оно и не нужно?
150© 2016 NetCracker Technology Corporation Confidential
Примеры, когда OQL пасует
• Если в одной коллекции хранятся разнородные данные, то OQL не подходит• EJB bean cache• Свои кэши данных
• Если данные разбиты по разным java-объектам, то OQL не подходит
151© 2016 NetCracker Technology Corporation Confidential
Ты ж программист
• Берём SQL engine: Apache Calcite
152© 2016 NetCracker Technology Corporation Confidential
Ты ж программист
• Берём SQL engine: Apache Calcite• Прикручиваем его к MAT: mat-calcite-plugin
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)
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
155© 2016 NetCracker Technology Corporation Confidential
Mat-calcite-plugin
• Плюсы:• Хорошая поддержка SQL• Ставится из MAT (“install new software…”)
156© 2016 NetCracker Technology Corporation Confidential
Mat-calcite-plugin
• Плюсы:• Хорошая поддержка SQL• Ставится из MAT (“install new software…”)
• Минусы:• Подходит не для каждого запроса: Calcite заточен
под full scan• Обход графа на SQL это та ещё радость
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; });
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
159© 2016 NetCracker Technology Corporation Confidential
Ты ж java программист
• Java object layout хорошо подходит для анализа индивидуальных объектов:http://hg.openjdk.java.net/code-tools/jol/…/samples/
160© 2016 NetCracker Technology Corporation Confidential
Ты ж java программист
• Java object layout хорошо подходит для анализа индивидуальных объектов:http://hg.openjdk.java.net/code-tools/jol/…/samples/
• Плюсы:• Управляется из java кода• Выдаёт точные значения
161© 2016 NetCracker Technology Corporation Confidential
Ты ж java программист
• Java object layout хорошо подходит для анализа индивидуальных объектов:http://hg.openjdk.java.net/code-tools/jol/…/samples/
• Плюсы:• Управляется из java кода• Выдаёт точные значения
• Минусы:• Управляется из java кода
162© 2016 NetCracker Technology Corporation Confidential
Выводы
• До OOM стараемся не доводить (-Xmx, thread pools)• Если довели, то снимаем хипдамп (jmap, coredump)• Обновляем JVM ради: исправления ошибок,
инструментария
163© 2016 NetCracker Technology Corporation Confidential
• Владимир Ситников• Performance engineer @ NetCracker• sitnikov@netcracker.com• @VladimirSitnikv
Спасибо
Спасибо
164© 2015 NetCracker Technology Corporation Confidential