Новый день, новая версия Java … приятно ?
Мы использовали для обновления второстепенных версий Java в основном из-за проблем безопасности. Но иногда эти незначительные обновления приносят нам совершенно новые, потрясающие функции. Так было, например, с 7u40, который принес нам потрясающий контроль полетов, известный из JRockit. (Если вы заинтересованы в отслеживании изменений в обновлениях Java, ознакомьтесь с
http://www.oracle.com/technetwork/java/javase/8all-relnotes-2226344.html для Java 8 или
http://www.java. com / en / download / faq / release_changes.xml для Java 7)
Та же ситуация сейчас с версиями
7u60 и
8u20 . Теперь флаги
MinHeapFreeRatio и
MaxHeapFreeRatio стало управляемым, что означает, что мы можем изменить его значения … во время выполнения ?
Вы всегда можете проверить, какими флагами в JVM можно управлять, вызвав
java -XX:+PrintFlagsFinal -XX:+UseG1GC -version |grep manageable intx CMSAbortablePrecleanWaitMillis = 100 {manageable} intx CMSWaitDuration = 2000 {manageable} bool HeapDumpAfterFullGC = false {manageable} bool HeapDumpBeforeFullGC = false {manageable} bool HeapDumpOnOutOfMemoryError = false {manageable} ccstr HeapDumpPath = {manageable} uintx MaxHeapFreeRatio = 70 {manageable} uintx MinHeapFreeRatio = 40 {manageable} bool PrintClassHistogram = false {manageable} bool PrintClassHistogramAfterFullGC = false {manageable} bool PrintClassHistogramBeforeFullGC = false {manageable} bool PrintConcurrentLocks = false {manageable} bool PrintGC = false {manageable} bool PrintGCDateStamps = false {manageable} bool PrintGCDetails = false {manageable} bool PrintGCTimeStamps = false {manageable} java version "1.8.0_20" Java(TM) SE Runtime Environment (build 1.8.0_20-b26) Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode)
Возвращаясь к нашим флагам. MinHeapFreeRatio определяет минимальный процент свободной кучи после GC, чтобы избежать расширения, в то время как
MaxHeapFreeRation (как вы можете ожидать) описывает максимальный процент свободной кучи после GC, чтобы избежать сжатия.
Теперь посмотрим, как работает изменение размера кучи. Сначала нам нужно найти Java-процесс для тестирования. Я собираюсь использовать запуск
IntelliJ IDEA .
Как вы знаете, java pids можно найти, вызвав
команду jps :
jps -l 17136 com.intellij.idea.Main
Мы уже знаем наш pid для тестирования, поэтому самое время узнать статистику кучи. Мы будем использовать
команду jmap для этого:
jmap -heap 17136 Attaching to process ID 17136, please wait... Debugger attached successfully. Server compiler detected. JVM version is 25.20-b23 using thread-local object allocation. Garbage-First (G1) GC with 4 thread(s) Heap Configuration: MinHeapFreeRatio = 40 MaxHeapFreeRatio = 70 MaxHeapSize = 2147483648 (2048.0MB) NewSize = 1363144 (1.2999954223632812MB) MaxNewSize = 1287651328 (1228.0MB) OldSize = 5452592 (5.1999969482421875MB) NewRatio = 2 SurvivorRatio = 8 MetaspaceSize = 21807104 (20.796875MB) CompressedClassSpaceSize = 1073741824 (1024.0MB) MaxMetaspaceSize = 17592186044415 MB G1HeapRegionSize = 1048576 (1.0MB) Heap Usage: G1 Heap: regions = 2048 capacity = 702545920 (670.0MB) used = 284513824 (271.3335266113281MB) free = 418032096 (398.6664733886719MB) 40.49754128527285% used
Как видите, я использую
G1 GC с максимальным размером кучи 2 ГБ (-Xmx2g). Использование кучи составляет около 40%. Теперь мы должны запустить full gc, чтобы немного очиститься перед игрой.
jcmd 17136 GC.run
Тогда jmap еще раз, и мы можем увидеть
Heap Configuration: MinHeapFreeRatio = 40 MaxHeapFreeRatio = 70 Heap Usage: G1 Heap: regions = 2048 capacity = 439353344 (419.0MB) used = 135954032 (129.65586853027344MB) free = 303399312 (289.34413146972656MB) 30.944121367607025% used
Наконец-то мы готовы начать сбор. Я изменю значение
флага MaxHeapFreeRatio с помощью
инструмента jinfo :
jinfo -flag MaxHeapFreeRatio=50 17136
После этого мы должны снова запустить full gc для принудительного изменения размера. И теперь наша куча выглядит так:
Heap Configuration: MinHeapFreeRatio = 40 MaxHeapFreeRatio = 50 Heap Usage: G1 Heap: regions = 2048 capacity = 166723584 (159.0MB) used = 82849400 (79.01134490966797MB) free = 83874184 (79.98865509033203MB) 49.69266975450816% used
Как видите, куча сократилась с 419 до 159 МБ.
Теперь мы можем попробовать пойти другим путем:
jinfo -flag MaxHeapFreeRatio=90 17136 jinfo -flag MinHeapFreeRatio=85 17136
дает
вывод
Jmap
Heap Configuration: MinHeapFreeRatio = 85 MaxHeapFreeRatio = 90 Heap Usage: G1 Heap: regions = 2048 capacity = 465567744 (444.0MB) used = 69816504 (66.58220672607422MB) free = 395751240 (377.4177932739258MB) 14.995992505872572% used
Изменение размера сработало еще раз, а объем кучи увеличился с 159 МБ до 444 МБ. Мы описали, что минимум 85% нашей емкости кучи должны быть свободными, и это указало JVM изменить размер кучи, чтобы получить максимально 15% использования. Теперь мы ждем смены среды выполнения XMX;)