SlideShare a Scribd company logo
1 of 166
© 2015 NetCracker Technology Corporation Confidential
Разбор сложных случаев OutOfMemoryError
Владимир Ситников
Jokerconf 2015
2© 2015 NetCracker Technology Corporation Confidential
• Владимир Ситников
• Performance engineer @ NetCracker
• sitnikov@netcracker.com
• @VladimirSitnikv
Кто я
3© 2015 NetCracker Technology Corporation Confidential
О чём доклад
• Разбор некоторых OutOfMemoryError
• Примеры подходов к анализу/защите от OOM
• OpenJDK/OracleJDK
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
• ...
5© 2015 NetCracker Technology Corporation Confidential
Дело о потерянном процессе
• Java процесс работал и пропал
6© 2015 NetCracker Technology Corporation Confidential
Дело о потерянном процессе
• Java процесс работал и пропал
• hs_err файл не появился
7© 2015 NetCracker Technology Corporation Confidential
Дело о потерянном процессе
• Java процесс работал и пропал
• hs_err файл не появился
• В out, err, log пусто
8© 2015 NetCracker Technology Corporation Confidential
Дело о потерянном процессе
• Java процесс работал и пропал
• hs_err файл не появился
• В out, err, log пусто
• Как так?
9© 2015 NetCracker Technology Corporation Confidential
OOMkiller
У Linux память конечна, и если она
заканчивается, то может случиться разное:
• умрёт невезучий процесс (по умолчанию)
10© 2015 NetCracker Technology Corporation Confidential
OOMkiller
У Linux память конечна, и если она
заканчивается, то может случиться разное:
• умрёт невезучий процесс (по умолчанию)
• malloc вернёт ошибку «нет памяти»
11© 2015 NetCracker Technology Corporation Confidential
OOMkiller
У Linux память конечна, и если она
заканчивается, то может случиться разное:
• умрёт невезучий процесс (по умолчанию)
• malloc вернёт ошибку «нет памяти»
Ключевое слово в Linux: vm.overcommit_memory=0
12© 2015 NetCracker Technology Corporation Confidential
Смотрим потребление памяти
$ top
PID VIRT RES COMMAND
18133 9606m 7.3g ora_dbw0_DB11
32600 2163m 843m /jdk170_55/bin/java -Xmx200m
17532 1757m 602m /jdk160_14/bin/java -Xmx1024m
13© 2015 NetCracker Technology Corporation Confidential
Смотрим потребление памяти
$ top
PID VIRT RES COMMAND
18133 9606m 7.3g ora_dbw0_DB11
32600 2163m 843m /jdk170_55/bin/java -Xmx200m
17532 1757m 602m /jdk160_14/bin/java -Xmx1024m
$ free –g (http://www.linuxatemyram.com/)
total used free
Mem: 31 31 0
-/+ buffers/cache: 10 21
Swap: 8 3 5
Занимаемая память
Свободная
память
14© 2015 NetCracker Technology Corporation Confidential
Смотрим потребление памяти
$ top
PID VIRT RES COMMAND
18133 9606m 7.3g ora_dbw0_DB11
32600 2163m 843m /jdk170_55/bin/java -Xmx200m
17532 1757m 602m /jdk160_14/bin/java -Xmx1024m
15© 2015 NetCracker Technology Corporation Confidential
Следим за native памятью
• -XX:+NativeMemoryTracking=[off|summary|detail]
16© 2015 NetCracker Technology Corporation Confidential
Следим за native памятью
• -XX:+NativeMemoryTracking=[off|summary|detail]
• Работает начиная с 1.7u40
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
18© 2015 NetCracker Technology Corporation Confidential
NMT на практике
19© 2015 NetCracker Technology Corporation Confidential
Ценный мех NMT
NMT позволяет
• более адресно заводить тикеты на OpenJDK
• проверять наличие утечек «служебной» памяти
Пример: GROOVY-7498 Groovy native memory leak
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
21© 2015 NetCracker Technology Corporation Confidential
Запускаем процесс
new ProcessBuilder("ping","123.321.123.321")
.start();
22© 2015 NetCracker Technology Corporation Confidential
Запускаем процесс
new ProcessBuilder("ping", "8.8.8.8")
.start();
23© 2015 NetCracker Technology Corporation Confidential
24© 2015 NetCracker Technology Corporation Confidential
На самом деле, можно
Если версия JDK свежая, то проблем нет:
• https://bugs.openjdk.java.net/browse/JDK-5049299
• 1.7u60+ всё ок
• 1.8u??+ (в 8u60 исправление есть наверняка)
25© 2015 NetCracker Technology Corporation Confidential
В предыдущих серияхверсиях
• ProcessBuilder#start() использует fork()
• -Xmx8g «по наследству» передаётся в ping
• В итоге ping либо не запустится, либо есть
шанс разбудить oomkiller
26© 2015 NetCracker Technology Corporation Confidential
Как запускать процессы в OpenJDK<1.7u60
• Либо вообще не запускать процессы
27© 2015 NetCracker Technology Corporation Confidential
Как запускать процессы в OpenJDK<1.7u60
• Либо вообще не запускать процессы
• Либо использовать jnr-posix (напрямую или из JRuby)
• https://github.com/jnr/jnr-posix
28© 2015 NetCracker Technology Corporation Confidential
OutOfMemoryError: unable to create native thread
• Кто виноват?
29© 2015 NetCracker Technology Corporation Confidential
OutOfMemoryError: unable to create native thread
• Кто виноват?
• 32bit JVM и в адресном пространстве уже негде выделить место
для стека (thread native stack)
30© 2015 NetCracker Technology Corporation Confidential
OutOfMemoryError: unable to create native thread
• Кто виноват?
• 32bit JVM и в адресном пространстве уже негде выделить место
для стека (thread native stack)
• Что делать?
• Переходить на 64bit JVM
31© 2015 NetCracker Technology Corporation Confidential
OutOfMemoryError: unable to create native thread
• Кто виноват?
• 32bit JVM и в адресном пространстве уже негде выделить место
для стека (thread native stack)
• Что делать?
• Переходить на 64bit JVM
• Или уменьшать -XX:ThreadStackSize, уменьшать -XX:MaxPermSize
32© 2015 NetCracker Technology Corporation Confidential
А какая у нас версия?
$ java -Xmx800m -version
Error occurred during initialization of VM
java.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)
33© 2015 NetCracker Technology Corporation Confidential
limits
$ ulimit –a
34© 2015 NetCracker Technology Corporation Confidential
limits
$ ulimit –a
virtual memory (kbytes, -v) unlimited
35© 2015 NetCracker Technology Corporation Confidential
limits
$ ulimit –a
virtual memory (kbytes, -v) unlimited
open files (-n) 16384
36© 2015 NetCracker Technology Corporation Confidential
limits
$ ulimit –a
virtual memory (kbytes, -v) unlimited
open files (-n) 16384
max user processes (-u) 100000
37© 2015 NetCracker Technology Corporation Confidential
limits
$ ulimit –a
virtual memory (kbytes, -v) unlimited
open files (-n) 16384
max user processes (-u) 100000
stack size (kbytes, -s) 10240
38© 2015 NetCracker Technology Corporation Confidential
Действия в случае OutOfMemoryError
try {
"основной_монитор".notifyAll();
} catch (OutOfMemoryError e) {
log.info("Нужно больше памяти", e);
}
39© 2015 NetCracker Technology Corporation Confidential
Действия в случае OutOfMemoryError
try {
"основной_монитор".notifyAll();
} catch (OutOfMemoryError e) {
log.info("Нужно больше памяти", e);
}
40© 2015 NetCracker Technology Corporation Confidential
Реальные проблемы
• OOM может получить любой поток в любой
момент времени
41© 2015 NetCracker Technology Corporation Confidential
Реальные проблемы
• OOM может получить любой поток в любой
момент времени
• Например, ReentrantLock в момент unlock
42© 2015 NetCracker Technology Corporation Confidential
Реальные проблемы
• OOM может получить любой поток в любой
момент времени
• Например, ReentrantLock в момент unlock
• И мы получим вечнозанятую блокировку,
сломанную ArrayBlockingQueue, …
43© 2015 NetCracker Technology Corporation Confidential
Реальные проблемы
• OOM может получить любой поток в любой
момент времени
• Например, ReentrantLock в момент unlock
• И мы получим вечнозанятую блокировку,
сломанную ArrayBlockingQueue, …
• Аналогично и в случае StackOverflowError
44© 2015 NetCracker Technology Corporation Confidential
В случае аварии
В случае OutOfMemoryError/StackOverflowError
гораздо правильнее делать так:
• System.exit(146)
• -XX:OnError="kill -9 %p"
45© 2015 NetCracker Technology Corporation Confidential
Java heap
• Хранит java объекты, их содержимое
46© 2015 NetCracker Technology Corporation Confidential
Java heap
• Хранит java объекты, их содержимое
• Очищается сборщиком мусора
47© 2015 NetCracker Technology Corporation Confidential
Java heap
• Хранит java объекты, их содержимое
• Очищается сборщиком мусора
• Бывает, заканчивается
48© 2015 NetCracker Technology Corporation Confidential
OutOfMemoryError: PermGen space
• Кто виноват?
• Размер PermGen слишком мал
• Загружено слишком много классов
49© 2015 NetCracker Technology Corporation Confidential
OutOfMemoryError: PermGen space
• Кто виноват?
• Размер PermGen слишком мал
• Загружено слишком много классов
• Что делать?
• Увеличивать perm gen: -XX:PermSize=512M -XX:MaxPermSize=512M
• Искать лишние классы: jmap –histo
50© 2015 NetCracker Technology Corporation Confidential
OutOfMemoryError: PermGen space
• Кто виноват?
• Размер PermGen слишком мал
• Загружено слишком много классов
• Что делать?
• Увеличивать perm gen: -XX:PermSize=512M -XX:MaxPermSize=512M
• Искать лишние классы: jmap –histo
• Обновлять java (в 8-ке будет ошибка Metadata space:)
51© 2015 NetCracker Technology Corporation Confidential
OutOfMemoryError: Java heap space
• Кто виноват?
• Выделено мало памяти
• Garbage Collector не успел собрать мусор
• Что делать?
• Выделять больше памяти: -Xms, -Xmx
• Анализировать использование памяти
52© 2015 NetCracker Technology Corporation Confidential
Как анализировать занятость heap
GC log фиксирует приход-расход памяти по времени
53© 2015 NetCracker Technology Corporation Confidential
Как анализировать занятость heap
GC log фиксирует приход-расход памяти по времени
• Как собрать: -Xloggc:logs/gc.log, -XX:+PrintGCDetails, и т.д.
54© 2015 NetCracker Technology Corporation Confidential
Как анализировать занятость heap
GC log фиксирует приход-расход памяти по времени
• Как собрать: -Xloggc:logs/gc.log, -XX:+PrintGCDetails, и т.д.
• Чем смотреть: GCViewer
55© 2015 NetCracker Technology Corporation Confidential
Как анализировать занятость heap
GC log фиксирует приход-расход памяти по времени
• Как собрать: -Xloggc:logs/gc.log, -XX:+PrintGCDetails, и т.д.
• Чем смотреть: GCViewer
• На что смотреть: «занятость памяти после full gc»
56© 2015 NetCracker Technology Corporation Confidential
GC лог здорового человека
• 60мс minor, 3sec major паузы
57© 2015 NetCracker Technology Corporation Confidential
GC лог курильщика
• Сплошные full gc
58© 2015 NetCracker Technology Corporation Confidential
Недоперепил
• Бывает, памяти остаётся мало
• GC постоянно как-то находит крохи мусора
59© 2015 NetCracker Technology Corporation Confidential
Недоперепил
• Бывает, памяти остаётся мало
• GC постоянно как-то находит крохи мусора
• А OutOfMemory всё нет и нет!
60© 2015 NetCracker Technology Corporation Confidential
Недоперепил
• Бывает, памяти остаётся мало
• GC постоянно как-то находит крохи мусора
• А OutOfMemory всё нет и нет!
• Что делать, шеф?
61© 2015 NetCracker Technology Corporation Confidential
Варианты действий, когда почти OOM
• Jmap – снимать дамп вручную
62© 2015 NetCracker Technology Corporation Confidential
Варианты действий, когда почти OOM
• Jmap – снимать дамп вручную
• GC overhead limit
63© 2015 NetCracker Technology Corporation Confidential
Варианты действий, когда почти OOM
• Jmap – снимать дамп вручную
• GC overhead limit
• -XX:GCHeapFreeLimit=20 (2 по умолчанию)
‒Если после full GC останется меньше X%, то OOM
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
65© 2015 NetCracker Technology Corporation Confidential
Чисто там, где не мусорят
• Java Flight Recorder / Java Mission Control
66© 2015 NetCracker Technology Corporation Confidential
Как понять, кто создаёт объекты?
Java Flight Recorder
• Позволяет узнать stack trace где создавались объекты
• Позволяет узнать объём выделяемой памяти
67© 2015 NetCracker Technology Corporation Confidential
Как понять, кто создаёт объекты?
Java Flight Recorder
• Позволяет узнать stack trace где создавались объекты
• Позволяет узнать объём выделяемой памяти
• Бесплатно на test серверах
68© 2015 NetCracker Technology Corporation Confidential
Как понять, кто создаёт объекты?
Java Flight Recorder
• Позволяет узнать stack trace где создавались объекты
• Позволяет узнать объём выделяемой памяти
• Бесплатно на test серверах
Запуск:
• -XX:+UnlockCommercialFeatures -XX:+FlightRecorder
-XX:FlightRecorderOptions=repository=jfr,defaultrecording=false
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
70© 2015 NetCracker Technology Corporation Confidential
OOM: heap space
Дамп памяти содержит снимок содержимого java heap
• Как собрать: -XX:HeapDumpOnOutOfMemoryError
71© 2015 NetCracker Technology Corporation Confidential
OOM: heap space
Дамп памяти содержит снимок содержимого java heap
• Как собрать: -XX:HeapDumpOnOutOfMemoryError
• jmap -dump
72© 2015 NetCracker Technology Corporation Confidential
OOM: heap space
Дамп памяти содержит снимок содержимого java heap
• Как собрать: -XX:HeapDumpOnOutOfMemoryError
• jmap -dump
• jmap -dump -F (force режим, если обычный не работает)
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
74© 2015 NetCracker Technology Corporation Confidential
75© 2015 NetCracker Technology Corporation Confidential
Скорость работы jmap
$jmap –dump ..
real 0m7.992s
user 0m0.304s
sys 0m0.067s
$ jmap –dump –F ..
real 24m4.378s
user 21m56.321s
sys 6m51.676s
76© 2015 NetCracker Technology Corporation Confidential
В тяжёлых случаях
• core dump быстрее и надёжнее чем jmap -dump <pid>
$ ulimit –c
core file size (blocks, -c) 33’222’111
77© 2015 NetCracker Technology Corporation Confidential
В тяжёлых случаях
• core dump быстрее и надёжнее чем jmap -dump <pid>
$ ulimit –c
core file size (blocks, -c) 33’222’111
• Из core dump можно получить hprof (через jmap …)
78© 2015 NetCracker Technology Corporation Confidential
• Дамп памяти содержит данные всех объектов
• Состояние потоков (thread dump)
• Значения локальных переменных
Дампы памяти
79© 2015 NetCracker Technology Corporation Confidential
• Дамп памяти содержит данные всех объектов
• Состояние потоков (thread dump)
• Значения локальных переменных
Дампы памяти
Да, пароли там
тоже есть
80© 2015 NetCracker Technology Corporation Confidential
• -Xmx2G, OracleJDK 1.8u60
java.lang.OutOfMemoryError: Java heap space
Dumping 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)
Маловато будет
81© 2015 NetCracker Technology Corporation Confidential
• -Xmx2G, OracleJDK 1.8u60
java.lang.OutOfMemoryError: Java heap space
Dumping 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
82© 2015 NetCracker Technology Corporation Confidential
Терминология
«утекла память», «потребилась память»
== кто-то мешает GC её освободить
83© 2015 NetCracker Technology Corporation Confidential
Кто может держать память?
• Потоки (threads)
84© 2015 NetCracker Technology Corporation Confidential
Кто может держать память?
• Потоки (threads)
• Локальные переменные
85© 2015 NetCracker Technology Corporation Confidential
Кто может держать память?
• Потоки (threads)
• Локальные переменные
• Кишки JVM
86© 2015 NetCracker Technology Corporation Confidential
Кто может держать память?
• Потоки (threads)
• Локальные переменные
• Кишки JVM
• И далее по цепочкам простых ссылок,
WeakReferences, SoftReferences,
PhantomReferences
87© 2015 NetCracker Technology Corporation Confidential
Кто может держать память?
• Потоки (threads)
• Локальные переменные
• Кишки JVM
• И далее по цепочкам простых ссылок,
WeakReferences, SoftReferences,
PhantomReferences, FinalReferences
‾√
88© 2015 NetCracker Technology Corporation Confidential
‾√
WeakHashMap<K, V>
K1 V1
K2 V2
89© 2015 NetCracker Technology Corporation Confidential
‾√
WeakHashMap<K, V>
K1 V1
K2 V2
90© 2015 NetCracker Technology Corporation Confidential
‾√
WeakHashMap<K, V>
91© 2015 NetCracker Technology Corporation Confidential
WeakHashMap<K, V>
K1 V1
K2 V2
√‾
92© 2015 NetCracker Technology Corporation Confidential
WeakHashMap<K, V>
K1 V1
K2 V2
√‾
93© 2015 NetCracker Technology Corporation Confidential
И освободится ли WeakHashMap<K, V>?
K1 V1
K2 V2
?√‾
94© 2015 NetCracker Technology Corporation Confidential
√‾
Освобождению не подлежит
K1 V1
K2 V2
95© 2015 NetCracker Technology Corporation Confidential
√‾
Освобождению не подлежит
K1 V1
K2 V2
96© 2015 NetCracker Technology Corporation Confidential
√‾
Освобождению не подлежит
K1 V1
K2 V2
97© 2015 NetCracker Technology Corporation Confidential
√‾
Освобождению не подлежит
K1 V1
K2 V2
98© 2015 NetCracker Technology Corporation Confidential
√‾
Освобождению не подлежит
K1 V1
K2 V2
99© 2015 NetCracker Technology Corporation Confidential
√‾
Освобождению не подлежит
K1 V1
K2 V2
100© 2015 NetCracker Technology Corporation Confidential
√‾
Освобождению не подлежит
K1 V1
K2 V2
101© 2015 NetCracker Technology Corporation Confidential
И кто же так делает?
• XML element
• Элемент хранит ссылку на документ, а тот на всё
остальное
102© 2015 NetCracker Technology Corporation Confidential
И кто же так делает?
• XML element
• Элемент хранит ссылку на документ, а тот на всё
остальное
• java.beans.…
103© 2015 NetCracker Technology Corporation Confidential
Пример из жизни
•Запускаем Groovy
104© 2015 NetCracker Technology Corporation Confidential
Пример из жизни
•Запускаем Groovy
•Из JSR223 API (scripting API)
105© 2015 NetCracker Technology Corporation Confidential
Пример из жизни
•Запускаем Groovy
•Из JSR223 API (scripting API)
•И получаем OutOfMemoryError
106© 2015 NetCracker Technology Corporation Confidential
Терминология
Для любого объекта Ы есть 2 основных метрики
• Shallow heap – объём памяти, занимаемый самим
объектом
• Retained heap – объём памяти, который освободится,
если Ы окажется мусором
107© 2015 NetCracker Technology Corporation Confidential
Dominator tree
2 3
4 5
№2 не доминирует №3
№4 доминирует №5
√‾
108© 2015 NetCracker Technology Corporation Confidential
Groovy + Scripting for Java (JSR 223) = печаль (demo1)
Демо: groovy
109© 2015 NetCracker Technology Corporation Confidential
Dominator Tree (demo1)
• Показывает объекты, которые держат больше всего других
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(); *
}
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;
112© 2015 NetCracker Technology Corporation Confidential
Throwable наносит ответный удар
• StackTraceElement это сплошные строки, но в
Throwable есть скрытое поле backtrace
113© 2015 NetCracker Technology Corporation Confidential
Throwable наносит ответный удар
• StackTraceElement это сплошные строки, но в
Throwable есть скрытое поле backtrace
• Оно прекрасно держит ссылки на классы из стектрейса
114© 2015 NetCracker Technology Corporation Confidential
Throwable наносит ответный удар
• StackTraceElement это сплошные строки, но в
Throwable есть скрытое поле backtrace
• Оно прекрасно держит ссылки на классы из стектрейса
• Иногда это может быть неожиданной ссылкой на класс
115© 2015 NetCracker Technology Corporation Confidential
Мораль
• Либо не используем «ControlFlowException»
• Либо не заполняем stacktrace
static final IllegalArgumentException
CFE = new IllegalArgumentException() {
public Throwable fillInStackTrace() {
return this;
}
}
116© 2015 NetCracker Technology Corporation Confidential
Object#finalize
Не стоит использовать finalizer’ы для «освобождения ресурсов»
• Finalizable объекты живут на 1 цикл GC (падают в old gen, ужас-
ужас)
117© 2015 NetCracker Technology Corporation Confidential
Object#finalize
Не стоит использовать finalizer’ы для «освобождения ресурсов»
• Finalizable объекты живут на 1 цикл GC (падают в old gen, ужас-
ужас)
• Невозможно объяснить JVM, что объект не надо
финализировать (если вручную вызвали .close)
118© 2015 NetCracker Technology Corporation Confidential
Object#finalize -> PhantomReference
PhantomReference позволяет организовать «автоматическое
освобождение ресурсов» с поддержкой ручного:
• PhantomReference сохраняется в какую-нибудь map/set
119© 2015 NetCracker Technology Corporation Confidential
Object#finalize -> PhantomReference
PhantomReference позволяет организовать «автоматическое
освобождение ресурсов» с поддержкой ручного:
• PhantomReference сохраняется в какую-нибудь map/set
• Если объект выходит из видимости, GC обрабатывает Phantom
120© 2015 NetCracker Technology Corporation Confidential
Object#finalize -> PhantomReference
PhantomReference позволяет организовать «автоматическое
освобождение ресурсов» с поддержкой ручного:
• PhantomReference сохраняется в какую-нибудь map/set
• Если объект выходит из видимости, GC обрабатывает Phantom
• Если пользователь закрыл объект вручную, то там же и
очищается Phantom
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();
}
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
123© 2015 NetCracker Technology Corporation Confidential
• @shipilёv: не все хипдампы одинаково полезны
Eclipse Memory Analyzer
124© 2015 NetCracker Technology Corporation Confidential
Puzzler
++i--
Что это?
125© 2015 NetCracker Technology Corporation Confidential
Puzzler
++i--
^^^ оператор подёргивания
126© 2014 NetCracker Technology Corporation Confidential
Демо
127© 2015 NetCracker Technology Corporation Confidential
Dominator Tree (demo2)
• Quiz: Может ли объект дважды попасть в Dominator Tree?
128© 2015 NetCracker Technology Corporation Confidential
Основные окна Eclipse MAT (demo2)
• Class Histogram
• Показывает суммарную информацию по классам
129© 2015 NetCracker Technology Corporation Confidential
Dominator Tree (demo2)
• Как не погрязнуть в вечном разворачивании плюсиков?
130© 2015 NetCracker Technology Corporation Confidential
Алгоритм анализа дампов в Eclipse MAT
• Retained Set
• Immediate Dominators
131© 2015 NetCracker Technology Corporation Confidential
Алгоритм анализа дампов в Eclipse MAT
• Dominator Tree
• Retained Set
• Immediate Dominators
132© 2015 NetCracker Technology Corporation Confidential
Алгоритм анализа дампов в Eclipse MAT
• Dominator Tree
• Retained Set
• Immediate Dominators
• Retained Set
• Immediate Dominators
• Retained Set
• Immediate Dominators
133© 2015 NetCracker Technology Corporation Confidential
Dominator Tree
• “Show Retained Set” показывает плоский список удерживаемых
объектов
134© 2015 NetCracker Technology Corporation Confidential
Immediate dominators
• Кто-то очень любит HashMap$Entry. Как узнать кто?
• Immediate dominators!
135© 2015 NetCracker Technology Corporation Confidential
HashMap$Entry
• Если очень захотеть, то можно сделать Map с
накладными расходами в 4 байта на запись
136© 2015 NetCracker Technology Corporation Confidential
HashMap
HashMap Entry[]
Entry
id
41
Entry
name
qwe
137© 2015 NetCracker Technology Corporation Confidential
HashMap: entry лишние
HashMap Entry[]
Entry
id
41
Entry
name
qwe
138© 2015 NetCracker Technology Corporation Confidential
HashMap
HashMap Entry[]
Entry
id
41
Entry
name
qwe
139© 2015 NetCracker Technology Corporation Confidential
CompactMap
CMap1 Object[]
41
qwe
CMap2
keypos
id=0
name=1
Object[]
42
rty
140© 2015 NetCracker Technology Corporation Confidential
HashMap$Entry
• Работает, если форма (состав ключей) у многих
объектов одинаковая
• Например, у всех объектов есть запись “width”=“100%”
141© 2015 NetCracker Technology Corporation Confidential
HashMap$Entry
• Работает, если форма (состав ключей) у многих
объектов одинаковая
• Например, у всех объектов есть запись “width”=“100%”
• https://github.com/vlsi/compactmap
• См. v8/design.html#prop_access
142© 2015 NetCracker Technology Corporation Confidential
CompactHashMap
HashMap -> CompactHashMap в реальном
проекте:
• 500МиБ –> 290МиБ
• 3.0 сек / 1M обращений -> 150 сек / 1M обращений
143© 2015 NetCracker Technology Corporation Confidential
CompactHashMap
HashMap -> CompactHashMap в реальном
проекте:
• 500МиБ –> 290МиБ
• 3.0 сек / 1M обращений -> 150 сек / 1M обращений
144© 2015 NetCracker Technology Corporation Confidential
ReservedCodeCacheSize
• Если у JIT компилятора заканчивается память,
то он перестаёт компилировать
145© 2015 NetCracker Technology Corporation Confidential
ReservedCodeCacheSize
• Если у JIT компилятора заканчивается память,
то он перестаёт компилировать
• В Weblogic/EE/… стандартных 64M мало
146© 2015 NetCracker Technology Corporation Confidential
ReservedCodeCacheSize
• Если у JIT компилятора заканчивается память,
то он перестаёт компилировать
• В Weblogic/EE/… стандартных 64M мало
• -XX:+ReservedCodeCacheSize=128m/192m
147© 2015 NetCracker Technology Corporation Confidential
CompactHashMap
HashMap -> CompactHashMap, -
XX:+ReservedCodeCacheSize=128m:
• 500МиБ –> 290МиБ
• 3.0 сек / 1M обращений -> 3.5 сек / 1M обращений
148© 2015 NetCracker Technology Corporation Confidential
Но как же автоматизация?
• В Eclipse есть Object Query Language
149© 2015 NetCracker Technology Corporation Confidential
Но как же автоматизация?
• В Eclipse есть Object Query Language
• В простых случаях даже работает
150© 2015 NetCracker Technology Corporation Confidential
Но как же автоматизация?
• В Eclipse есть ограниченный :( Object Query Language
• Нет group by
• Нет join
• Нет distinct
151© 2015 NetCracker Technology Corporation Confidential
OQL!
• В Eclipse есть ограниченный :( Object Query Language
• Нет group by
• Нет join
• Нет distinct
• Может, оно и не нужно?
152© 2015 NetCracker Technology Corporation Confidential
Примеры, когда OQL пасует
• Если в одной коллекции хранятся разнородные
данные, то OQL не подходит
• EJB bean cache
• Свои кэши данных
• Если данные разбиты по разным java-объектам, то
OQL не подходит
153© 2015 NetCracker Technology Corporation Confidential
Ты ж программист
• Берём SQL engine: Apache Calcite
154© 2015 NetCracker Technology Corporation Confidential
Ты ж программист
• Берём SQL engine: Apache Calcite
• Прикручиваем его к MAT: mat-calcite-plugin
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)
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
157© 2015 NetCracker Technology Corporation Confidential
Mat-calcite-plugin
• Плюсы:
• Хорошая поддержка SQL
• Ставится из MAT (“install new software…”)
158© 2015 NetCracker Technology Corporation Confidential
Mat-calcite-plugin
• Плюсы:
• Хорошая поддержка SQL
• Ставится из MAT (“install new software…”)
• Минусы:
• Подходит не для каждого запроса: Calcite заточен
под full scan
• Обход графа на SQL это та ещё радость
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; });
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
161© 2015 NetCracker Technology Corporation Confidential
Ты ж java программист
• Java object layout хорошо подходит для анализа
индивидуальных объектов:
http://hg.openjdk.java.net/code-tools/jol/…/samples/
162© 2015 NetCracker Technology Corporation Confidential
Ты ж java программист
• Java object layout хорошо подходит для анализа
индивидуальных объектов:
http://hg.openjdk.java.net/code-tools/jol/…/samples/
• Плюсы:
• Управляется из java кода
• Выдаёт точные значения
163© 2015 NetCracker Technology Corporation Confidential
Ты ж java программист
• Java object layout хорошо подходит для анализа
индивидуальных объектов:
http://hg.openjdk.java.net/code-tools/jol/…/samples/
• Плюсы:
• Управляется из java кода
• Выдаёт точные значения
• Минусы:
• Управляется из java кода
164© 2015 NetCracker Technology Corporation Confidential
Выводы
• До OOM стараемся не доводить (-Xmx, thread pools, и т.п.)
• Если довели, то снимаем хипдамп (jmap, coredump)
• Обновляем JVM ради: исправления ошибок, инструментария
165© 2015 NetCracker Technology Corporation Confidential
• Владимир Ситников
• Performance engineer @ NetCracker
• sitnikov@netcracker.com
• @VladimirSitnikv
Спасибо
Спасибо
166© 2015 NetCracker Technology Corporation Confidential

More Related Content

What's hot

Производительность open source решений
Производительность open source решенийПроизводительность open source решений
Производительность open source решенийVladimir Sitnikov
 
Zabbix 3.4 - простая непростая дружба с сообществом / Алексей Владышев (Zabbix)
Zabbix 3.4 - простая непростая дружба с сообществом / Алексей Владышев (Zabbix)Zabbix 3.4 - простая непростая дружба с сообществом / Алексей Владышев (Zabbix)
Zabbix 3.4 - простая непростая дружба с сообществом / Алексей Владышев (Zabbix)Ontico
 
Быстрое построение backendов c помощью реактивных потоков
Быстрое построение backendов c помощью реактивных потоковБыстрое построение backendов c помощью реактивных потоков
Быстрое построение backendов c помощью реактивных потоковCodeFest
 
Организация процесса регулярной обработки больших объемов данных
Организация процесса регулярной обработки больших объемов данныхОрганизация процесса регулярной обработки больших объемов данных
Организация процесса регулярной обработки больших объемов данныхCodeFest
 
Deployment to production with an unexpected load
Deployment to production with an unexpected loadDeployment to production with an unexpected load
Deployment to production with an unexpected loadGrid Dynamics
 
Kubernetes
KubernetesKubernetes
KubernetesSQALab
 
Zabbix 3.2 - мониторинг качественно нового уровня / Алексей Владышев (Zabbix)
Zabbix 3.2 - мониторинг качественно нового уровня / Алексей Владышев (Zabbix)Zabbix 3.2 - мониторинг качественно нового уровня / Алексей Владышев (Zabbix)
Zabbix 3.2 - мониторинг качественно нового уровня / Алексей Владышев (Zabbix)Ontico
 
Реактивный двигатель вашего Android приложения
Реактивный двигатель вашего Android приложенияРеактивный двигатель вашего Android приложения
Реактивный двигатель вашего Android приложенияMatvey Malkov
 
Selenium grid on-demand
Selenium grid on-demandSelenium grid on-demand
Selenium grid on-demandSQALab
 
Что нам стоит DAL построить? Акуляков Артём D2D Just.NET
Что нам стоит DAL построить? Акуляков Артём D2D Just.NETЧто нам стоит DAL построить? Акуляков Артём D2D Just.NET
Что нам стоит DAL построить? Акуляков Артём D2D Just.NETDev2Dev
 
Алексей Романчук «Реактивное программирование»
Алексей Романчук «Реактивное программирование»Алексей Романчук «Реактивное программирование»
Алексей Романчук «Реактивное программирование»DevDay
 
Практика Lock-free. RealTime-сервер
Практика Lock-free. RealTime-серверПрактика Lock-free. RealTime-сервер
Практика Lock-free. RealTime-серверPlatonov Sergey
 
Ангелы и демоны многопоточного программирования / Алексей Федоров (Одноклассн...
Ангелы и демоны многопоточного программирования / Алексей Федоров (Одноклассн...Ангелы и демоны многопоточного программирования / Алексей Федоров (Одноклассн...
Ангелы и демоны многопоточного программирования / Алексей Федоров (Одноклассн...Ontico
 
Ядро автоматизации под микро-сервисную архитектуру
Ядро автоматизации под микро-сервисную архитектуруЯдро автоматизации под микро-сервисную архитектуру
Ядро автоматизации под микро-сервисную архитектуруSQALab
 
Micro orm для жизни. Кожевников Дмитрий D2D Just.NET
Micro orm для жизни. Кожевников Дмитрий D2D Just.NETMicro orm для жизни. Кожевников Дмитрий D2D Just.NET
Micro orm для жизни. Кожевников Дмитрий D2D Just.NETDev2Dev
 
Всевидящее око. Мониторинг нагрузочного тестирования с InfluxDB и Grafana
Всевидящее око. Мониторинг нагрузочного тестирования с InfluxDB и GrafanaВсевидящее око. Мониторинг нагрузочного тестирования с InfluxDB и Grafana
Всевидящее око. Мониторинг нагрузочного тестирования с InfluxDB и GrafanaSQALab
 
Как сделать ваш JavaScript быстрее
Как сделать ваш JavaScript быстрееКак сделать ваш JavaScript быстрее
Как сделать ваш JavaScript быстрееRoman Dvornov
 
Артём Ерошенко «Рецепт приготовления облачных тестингов»
Артём Ерошенко «Рецепт приготовления облачных тестингов»Артём Ерошенко «Рецепт приготовления облачных тестингов»
Артём Ерошенко «Рецепт приготовления облачных тестингов»WrikeTechClub
 
Олег Миколайченко "Как перестать хранить секреты в git и начать использовать ...
Олег Миколайченко "Как перестать хранить секреты в git и начать использовать ...Олег Миколайченко "Как перестать хранить секреты в git и начать использовать ...
Олег Миколайченко "Как перестать хранить секреты в git и начать использовать ...Fwdays
 

What's hot (20)

Производительность open source решений
Производительность open source решенийПроизводительность open source решений
Производительность open source решений
 
Zabbix 3.4 - простая непростая дружба с сообществом / Алексей Владышев (Zabbix)
Zabbix 3.4 - простая непростая дружба с сообществом / Алексей Владышев (Zabbix)Zabbix 3.4 - простая непростая дружба с сообществом / Алексей Владышев (Zabbix)
Zabbix 3.4 - простая непростая дружба с сообществом / Алексей Владышев (Zabbix)
 
Быстрое построение backendов c помощью реактивных потоков
Быстрое построение backendов c помощью реактивных потоковБыстрое построение backendов c помощью реактивных потоков
Быстрое построение backendов c помощью реактивных потоков
 
Организация процесса регулярной обработки больших объемов данных
Организация процесса регулярной обработки больших объемов данныхОрганизация процесса регулярной обработки больших объемов данных
Организация процесса регулярной обработки больших объемов данных
 
Deployment to production with an unexpected load
Deployment to production with an unexpected loadDeployment to production with an unexpected load
Deployment to production with an unexpected load
 
Kubernetes
KubernetesKubernetes
Kubernetes
 
Zabbix 3.2 - мониторинг качественно нового уровня / Алексей Владышев (Zabbix)
Zabbix 3.2 - мониторинг качественно нового уровня / Алексей Владышев (Zabbix)Zabbix 3.2 - мониторинг качественно нового уровня / Алексей Владышев (Zabbix)
Zabbix 3.2 - мониторинг качественно нового уровня / Алексей Владышев (Zabbix)
 
Реактивный двигатель вашего Android приложения
Реактивный двигатель вашего Android приложенияРеактивный двигатель вашего Android приложения
Реактивный двигатель вашего Android приложения
 
Selenium grid on-demand
Selenium grid on-demandSelenium grid on-demand
Selenium grid on-demand
 
10M tests per day
10M tests per day10M tests per day
10M tests per day
 
Что нам стоит DAL построить? Акуляков Артём D2D Just.NET
Что нам стоит DAL построить? Акуляков Артём D2D Just.NETЧто нам стоит DAL построить? Акуляков Артём D2D Just.NET
Что нам стоит DAL построить? Акуляков Артём D2D Just.NET
 
Алексей Романчук «Реактивное программирование»
Алексей Романчук «Реактивное программирование»Алексей Романчук «Реактивное программирование»
Алексей Романчук «Реактивное программирование»
 
Практика Lock-free. RealTime-сервер
Практика Lock-free. RealTime-серверПрактика Lock-free. RealTime-сервер
Практика Lock-free. RealTime-сервер
 
Ангелы и демоны многопоточного программирования / Алексей Федоров (Одноклассн...
Ангелы и демоны многопоточного программирования / Алексей Федоров (Одноклассн...Ангелы и демоны многопоточного программирования / Алексей Федоров (Одноклассн...
Ангелы и демоны многопоточного программирования / Алексей Федоров (Одноклассн...
 
Ядро автоматизации под микро-сервисную архитектуру
Ядро автоматизации под микро-сервисную архитектуруЯдро автоматизации под микро-сервисную архитектуру
Ядро автоматизации под микро-сервисную архитектуру
 
Micro orm для жизни. Кожевников Дмитрий D2D Just.NET
Micro orm для жизни. Кожевников Дмитрий D2D Just.NETMicro orm для жизни. Кожевников Дмитрий D2D Just.NET
Micro orm для жизни. Кожевников Дмитрий D2D Just.NET
 
Всевидящее око. Мониторинг нагрузочного тестирования с InfluxDB и Grafana
Всевидящее око. Мониторинг нагрузочного тестирования с InfluxDB и GrafanaВсевидящее око. Мониторинг нагрузочного тестирования с InfluxDB и Grafana
Всевидящее око. Мониторинг нагрузочного тестирования с InfluxDB и Grafana
 
Как сделать ваш JavaScript быстрее
Как сделать ваш JavaScript быстрееКак сделать ваш JavaScript быстрее
Как сделать ваш JavaScript быстрее
 
Артём Ерошенко «Рецепт приготовления облачных тестингов»
Артём Ерошенко «Рецепт приготовления облачных тестингов»Артём Ерошенко «Рецепт приготовления облачных тестингов»
Артём Ерошенко «Рецепт приготовления облачных тестингов»
 
Олег Миколайченко "Как перестать хранить секреты в git и начать использовать ...
Олег Миколайченко "Как перестать хранить секреты в git и начать использовать ...Олег Миколайченко "Как перестать хранить секреты в git и начать использовать ...
Олег Миколайченко "Как перестать хранить секреты в git и начать использовать ...
 

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

Контейнеры в OpenStack: простое решение сложных проблем
Контейнеры в OpenStack: простое решение сложных проблемКонтейнеры в OpenStack: простое решение сложных проблем
Контейнеры в OpenStack: простое решение сложных проблемYandex
 
Контейнеры в OpenStack: простое решение сложных проблем
Контейнеры в OpenStack: простое решение сложных проблемКонтейнеры в OpenStack: простое решение сложных проблем
Контейнеры в OpenStack: простое решение сложных проблемOpenVZ
 
Баба-Яга против! — Роман Дворнов, Ostrovok.ru
Баба-Яга против! — Роман Дворнов, Ostrovok.ruБаба-Яга против! — Роман Дворнов, Ostrovok.ru
Баба-Яга против! — Роман Дворнов, Ostrovok.ruYandex
 
Баба Яга против!
Баба Яга против!Баба Яга против!
Баба Яга против!Roman Dvornov
 
How to cook a blockchain and not get burned
How to cook a blockchain and not get burned How to cook a blockchain and not get burned
How to cook a blockchain and not get burned Alexander Syrotenko
 
Алексей Федоров
Алексей ФедоровАлексей Федоров
Алексей ФедоровCodeFest
 
101 способ провести нагрузочное тестирование неправильно
101 способ провести нагрузочное тестирование неправильно101 способ провести нагрузочное тестирование неправильно
101 способ провести нагрузочное тестирование неправильноSQALab
 
Java Platform Performance BoF
Java Platform Performance BoFJava Platform Performance BoF
Java Platform Performance BoFDmitry Buzdin
 
Ciklum Odessa PHP Saturday - Dependency Injection
Ciklum Odessa PHP Saturday - Dependency InjectionCiklum Odessa PHP Saturday - Dependency Injection
Ciklum Odessa PHP Saturday - Dependency InjectionPavel Voznenko
 
D2D Pizza JS Илья Беда "Куда мы все катимся?"
D2D Pizza JS Илья Беда "Куда мы все катимся?"D2D Pizza JS Илья Беда "Куда мы все катимся?"
D2D Pizza JS Илья Беда "Куда мы все катимся?"Dev2Dev
 
Игры с виртуализацией в JavaScript, или как я переписал эмулятор, Евгений Пот...
Игры с виртуализацией в JavaScript, или как я переписал эмулятор, Евгений Пот...Игры с виртуализацией в JavaScript, или как я переписал эмулятор, Евгений Пот...
Игры с виртуализацией в JavaScript, или как я переписал эмулятор, Евгений Пот...Ontico
 
Некриптографическое исследование носителей православной криптографии
Некриптографическое исследование носителей  православной криптографииНекриптографическое исследование носителей  православной криптографии
Некриптографическое исследование носителей православной криптографииSergey Soldatov
 
Оптимизация UI потока / Дмитрий Куркин (Mail.Ru)
Оптимизация UI потока / Дмитрий Куркин (Mail.Ru)Оптимизация UI потока / Дмитрий Куркин (Mail.Ru)
Оптимизация UI потока / Дмитрий Куркин (Mail.Ru)Ontico
 
С чего начать свой путь этичного хакера? - Вадим Чакрян
С чего начать свой путь этичного хакера? - Вадим ЧакрянС чего начать свой путь этичного хакера? - Вадим Чакрян
С чего начать свой путь этичного хакера? - Вадим ЧакрянHackIT Ukraine
 
Поговорим про память
Поговорим про памятьПоговорим про память
Поговорим про памятьAndrey Akinshin
 
Валерий Петров «Модель памяти .NET»
Валерий Петров «Модель памяти .NET»Валерий Петров «Модель памяти .NET»
Валерий Петров «Модель памяти .NET»SpbDotNet Community
 
Easy authcache 2 кеширование для pro родионов игорь
Easy authcache 2   кеширование для pro родионов игорьEasy authcache 2   кеширование для pro родионов игорь
Easy authcache 2 кеширование для pro родионов игорьdrupalconf
 
Easy authcache 2 кэширование для pro. Родионов Игорь
Easy authcache 2   кэширование для pro. Родионов ИгорьEasy authcache 2   кэширование для pro. Родионов Игорь
Easy authcache 2 кэширование для pro. Родионов ИгорьPVasili
 
Joker 2015. WILD microSERVICES
Joker 2015. WILD microSERVICESJoker 2015. WILD microSERVICES
Joker 2015. WILD microSERVICESAleksandr Tarasov
 

Similar to Разбор сложных случаев OutOfMemoryError (20)

Контейнеры в OpenStack: простое решение сложных проблем
Контейнеры в OpenStack: простое решение сложных проблемКонтейнеры в OpenStack: простое решение сложных проблем
Контейнеры в OpenStack: простое решение сложных проблем
 
Контейнеры в OpenStack: простое решение сложных проблем
Контейнеры в OpenStack: простое решение сложных проблемКонтейнеры в OpenStack: простое решение сложных проблем
Контейнеры в OpenStack: простое решение сложных проблем
 
Баба-Яга против! — Роман Дворнов, Ostrovok.ru
Баба-Яга против! — Роман Дворнов, Ostrovok.ruБаба-Яга против! — Роман Дворнов, Ostrovok.ru
Баба-Яга против! — Роман Дворнов, Ostrovok.ru
 
Баба Яга против!
Баба Яга против!Баба Яга против!
Баба Яга против!
 
How to cook a blockchain and not get burned
How to cook a blockchain and not get burned How to cook a blockchain and not get burned
How to cook a blockchain and not get burned
 
Алексей Федоров
Алексей ФедоровАлексей Федоров
Алексей Федоров
 
101 способ провести нагрузочное тестирование неправильно
101 способ провести нагрузочное тестирование неправильно101 способ провести нагрузочное тестирование неправильно
101 способ провести нагрузочное тестирование неправильно
 
Java Platform Performance BoF
Java Platform Performance BoFJava Platform Performance BoF
Java Platform Performance BoF
 
Ciklum Odessa PHP Saturday - Dependency Injection
Ciklum Odessa PHP Saturday - Dependency InjectionCiklum Odessa PHP Saturday - Dependency Injection
Ciklum Odessa PHP Saturday - Dependency Injection
 
D2D Pizza JS Илья Беда "Куда мы все катимся?"
D2D Pizza JS Илья Беда "Куда мы все катимся?"D2D Pizza JS Илья Беда "Куда мы все катимся?"
D2D Pizza JS Илья Беда "Куда мы все катимся?"
 
Игры с виртуализацией в JavaScript, или как я переписал эмулятор, Евгений Пот...
Игры с виртуализацией в JavaScript, или как я переписал эмулятор, Евгений Пот...Игры с виртуализацией в JavaScript, или как я переписал эмулятор, Евгений Пот...
Игры с виртуализацией в JavaScript, или как я переписал эмулятор, Евгений Пот...
 
Некриптографическое исследование носителей православной криптографии
Некриптографическое исследование носителей  православной криптографииНекриптографическое исследование носителей  православной криптографии
Некриптографическое исследование носителей православной криптографии
 
Оптимизация UI потока / Дмитрий Куркин (Mail.Ru)
Оптимизация UI потока / Дмитрий Куркин (Mail.Ru)Оптимизация UI потока / Дмитрий Куркин (Mail.Ru)
Оптимизация UI потока / Дмитрий Куркин (Mail.Ru)
 
С чего начать свой путь этичного хакера? - Вадим Чакрян
С чего начать свой путь этичного хакера? - Вадим ЧакрянС чего начать свой путь этичного хакера? - Вадим Чакрян
С чего начать свой путь этичного хакера? - Вадим Чакрян
 
Поговорим про память
Поговорим про памятьПоговорим про память
Поговорим про память
 
Валерий Петров «Модель памяти .NET»
Валерий Петров «Модель памяти .NET»Валерий Петров «Модель памяти .NET»
Валерий Петров «Модель памяти .NET»
 
Easy authcache 2 кеширование для pro родионов игорь
Easy authcache 2   кеширование для pro родионов игорьEasy authcache 2   кеширование для pro родионов игорь
Easy authcache 2 кеширование для pro родионов игорь
 
Easy authcache 2 кэширование для pro. Родионов Игорь
Easy authcache 2   кэширование для pro. Родионов ИгорьEasy authcache 2   кэширование для pro. Родионов Игорь
Easy authcache 2 кэширование для pro. Родионов Игорь
 
Joker 2015. WILD microSERVICES
Joker 2015. WILD microSERVICESJoker 2015. WILD microSERVICES
Joker 2015. WILD microSERVICES
 
Joker 2015 Wild microSERVICES
Joker 2015 Wild microSERVICESJoker 2015 Wild microSERVICES
Joker 2015 Wild microSERVICES
 

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

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