Информация по семинару

Мастер-класс прошёл 23 января 2024.

Описание мастер-класса

В экосистеме Java существует большое количество инструментов диагностики и профилирования. Но есть нюанс , как правило инструменты с графическим интерфейсом работают либо с локальными процессами (а у нас сервер-сайд), либо требуют инфраструктуры и предварительной интеграции (например решения класса APM ).
А можно ли просто зайти в консоль и понять, что происходит с нашим приложением?

Можно! - и это будет предметом данного семинара.

JDK включает в свой состав ряд важных инструментов доступных из командной строки. Например, JDK Flight Recorder - мощный инструмент, все возможности, которого доступны из командной строки. Помимо этого мы поработаем с SJK open source инструментом, созданным автором данного семинара.
В рамках семинара будет две основные темы.

  • Приёмы диагностики JVM процесса из командной строки для локально запущенного процесса.
  • Особенности JVM в контейнере и возможности диагностики и удалённое подключение к JVM в контейнере использую JMX.
  • Видео запись

    Подготовка к семинару

    Важно!

    Для выполнения практической части вебинара, пожалуйста, заранее, проведите подготовку по инструкции представленной ниже.

    Необходимое ПО

    Для выполнения практической части семинара вам понадобится компьютер. Материал протестирован на Windows 10/11, Linux и MacOS.

    У вас долноам понадобиться следующее ПО.

  • Java 17 JDK - можно более старшую версию, но материал проверен на Adoptium Java 17
  • Apache Maven 3.8 или старше
  • git - клиент командной строки
  • Docker или аналог - при подготовке использовалась версия 20.10
  • TCP порты

    Следующие порты используются тестовыми приложениями и должны быть заняты другим ПО в ходе мастер-класса:

  • 5555
  • 8080
  • 9005
  • 9006
  • 8983
  • 11222
  • 23045
  • Погдотовка ПО

    Java 17

    Вам потребуется OpenJDK 17. Существует несколько дистрибутивов, вы може использовать любой. Ниже не полный список дистрибьюторов OpenJDK.

    После установке убедитесь, что бинарники JDK доступны в $PATH. Комманда java -version должна выкодить корректную версию.

    git

    Для работы с материалом семинара вам понадобится git клиент с поддержкой коммандной строки.

    Maven

    Для запуска демонстрационных проектов необходим Maven версии 3.8 или выше.

    После инсталяции убедитесь, что команда mvn --version корректно работает из консоли и возвращает правильные номера версий Java и Maven.

    Загрузка материалов

    Дальнейшие инструкции предполагают, что директория LABDIR используется для установки учебных материалов.

    Директории LABDIR выполните команду: git clone -b perfdemo-5.2.x https://github.com/aragozin/BroadLeafCommerce-DemoSite.git blf-demo

    SJK - консольный профайлер, который мы так же будем использовать.
    Скачайте sjk.jar и поместите в дидекториюLABDIR/blf-demo.

    В директории LABDIR/blf-demo проверьте запуск SJK java -jar sjk.jar --commands Команда должна распечатать список инструментов SJK, аналогичный примеру ниже. ssa - [Stack Sample Analyzer] Analyzing stack trace dumps hh - [Heap Histo] Prints class histogram, similar to jmap -histo stcpy - [Stack Copy] Stack dump copy/filtering utility vminfo - [VMINFO] Dumps various from local VM mx - [MBean] MBean query and invokation jps - [JPS] Enhanced version of JDK's jps tool mxping - [MXPING] Verify JMX connection to target JVM mxdump - null ttop - [Thread Top] Displays threads from JVM process dexp - [Dump Export] Extract metrics form compressed dump into tabular format jfr2json - [JFR 2 JSON] Flight decoder, command translates JFR files into JSON mprx - JMX proxy - expose target process' MBeans for remote access stcap - [Stack Capture] Dumps stack traces to file for further processing gc - [Print GC] Print GC log like information for remote process flame - Generates flame graph from stack traces

    Запуск тетового примера

    В директории LABDIR/blf-demo выполните команду mvn -P run_n_load test Первый запуск потребует несколько минут, по итогу maven сборка должна завершиться успешно.

    После завершения сбоки зайдите на URL http://127.0.0.1:8080/ Вы должны увидеть фронтэнд магазина “HEAT CLINIC”

    CPU системы должен быть загружен java процессами, так как предыдущая команда включает генератор нагрузки.

    В директории LABDIR/blf-demo выполните команду mvn clean

    Если директория LABDIR/blf-demo/pids не была удалена предидущей коммандой. Удалите её врeчную (например rm -rf LABDIR/blf-demo/pids).

    Запущенные на предыдущем шаге java процессы должны завершиться.

    Запуск тестового приложения в контейнере

    В директории LABDIR/blf-demo выполните команду mvn -P build_image,run_n_load_docker package Как и в предыдущем примере, после завершения сбоки зайдите на URL http://127.0.0.1:8080/ и проверте наличие страницы тестового приложения.

    CPU системы должен быть загружен java процессами как и в предидущем случае.

    Остановите контейнер и вспомогательные процессы docker stop storefront mvn clean Если директория LABDIR/blf-demo/pids не была удалена предидущей коммандой. Удалите её вручную (например rm -rf LABDIR/blf-demo/pids).

    Выполните команду jcmd чтобы убидится, что процессы лаборатоного стенда не запущены.

    Практическая часть

    Основы работы из коммандной строки

    Для работы нам понадобяться две консоли (условно A и B).

    Обновим демострационные материалы.

    1 в директории LABDIR/blf-demo выполним команду git pull так нужно скачать и поместить в LABDIR/blf-demo последнюю версию sjk.jar

    Запустим демонстрационный стенд.

    2 в директории LABDIR/blf-demo выполним команду mvn -P run_n_load test Команда требует значительного времени для запуска окружения. Сборка должна завершиться успешно.

    Проверим доступность приложения по ссылке http://127.0.0.1:8080.

    Оценим загрузку ЦПУ в системе.

    3 Воспользуйтесь коммандой top или менеджером процессов чтобы получить список процесов потребляющих ЦПУ.

    Воспользуемся средствани OpenJDK для поиска java процессов

    4 выполним команду jps резудьтатом команды будет список java процессов. 13793 LoadGenStarter 13444 HsqlStarter 13478 SolrStarter 13884 Jps 13535 SiteApplication 5 далее выполним комманду jcmd и также получим список процессов 13793 info.ragozin.loadgen.LoadGenStarter 13906 jdk.jcmd/sun.tools.jcmd.JCmd 13444 info.ragozin.hsql.HsqlStarter 13478 info.ragozin.solr.SolrStarter 13535 com.community.SiteApplication

    SJK так же имеет аналогичную команду.

    6 в директории LABDIR/blf-demo выполним команду java -jar sjk.jar jps 13793 info.ragozin.loadgen.LoadGenStarter 13444 info.ragozin.hsql.HsqlStarter 13478 info.ragozin.solr.SolrStarter 13929 sjk.jar jps 13948 org.gridkit.jvmtool.SJK jps 13535 com.community.SiteApplication 7 затем java -jar sjk.jar jps -pd PID MAIN XMaxHeapSize 13793 LoadGenStarter -XX:MaxHeapSize=4120903680 13444 HsqlStarter -XX:MaxHeapSize=314572800 13478 SolrStarter -XX:MaxHeapSize=314572800 14027 sjk.jar -XX:MaxHeapSize=4120903680 14046 SJK 13535 SiteApplication -XX:MaxHeapSize=536870912 данная команда успользует кастомизированный формат вывода, включающий размер Java кучи для каждного процесса.

    8 подробную информацию об опциях данной команды можно получить из встроенной справки java -jar sjk.jar jps --help

    Вернёмся к jcmd и посмотрим на её возможности

    9 выполним команду jcmd нас интересует PID Spring приложения SiteApplication 14081 jdk.jcmd/sun.tools.jcmd.JCmd 13793 info.ragozin.loadgen.LoadGenStarter 13444 info.ragozin.hsql.HsqlStarter 13478 info.ragozin.solr.SolrStarter 13535 com.community.SiteApplication 10 затем выполним jcmd $PID help The following commands are available: Compiler.CodeHeap_Analytics Compiler.codecache Compiler.codelist Compiler.directives_add Compiler.directives_clear Compiler.directives_print Compiler.directives_remove Compiler.perfmap Compiler.queue GC.class_histogram GC.finalizer_info GC.heap_dump GC.heap_info GC.run GC.run_finalization JFR.check JFR.configure JFR.dump JFR.start JFR.stop JVMTI.agent_load JVMTI.data_dump ManagementAgent.start ManagementAgent.start_local ManagementAgent.status ManagementAgent.stop System.trim_native_heap Thread.print VM.cds VM.class_hierarchy VM.classloader_stats VM.classloaders VM.command_line VM.dynlibs VM.events VM.flags VM.info VM.log VM.metaspace VM.native_memory VM.print_touched_methods VM.set_flag VM.stringtable VM.symboltable VM.system_properties VM.systemdictionary VM.uptime VM.version help список комманд может отличаться для различных версий JVM.

    Информация о потоках JVM

    Дамп потоков может нам помочь оцениться состояние приложения

    11 в директории LABDIR/blf-demo выполним команду jcmd $PID Thread.print

    12 Комады jcmd могут принимать дополнительные парамерты.
    Выполните команду jcmd $PID help Thread.print Thread.print Print all threads with stacktraces. Impact: Medium: Depends on the number of threads. Permission: java.lang.management.ManagementPermission(monitor) Syntax : Thread.print [options] Options: (options must be specified using the <key> or <key>=<value> syntax) -l : [optional] print java.util.concurrent locks (BOOLEAN, false) -e : [optional] print extended thread information (BOOLEAN, false)

    13 Aналогично можно использовать команду jstack jstack $PID

    Команда SJK ttop позволяет получить "top" по потокам в java процесса.

    14 выполним команду java -jar sjk.jar ttop -p $PID Restarting java with unlocked package access Monitoring threads ... 2024-01-23T14:25:27.582+0300 Process summary process cpu=274.22% application cpu=134.08% (user=121.50% sys=12.58%) other: cpu=140.14% thread count: 88 heap allocation rate 76mb/s [000096] user= 8.65% sys= 0.81% alloc= 6090kb/s - http-nio-8080-exec-16 [000091] user= 8.23% sys= 1.20% alloc= 5850kb/s - http-nio-8080-exec-11 [000097] user= 8.23% sys= 0.78% alloc= 5638kb/s - http-nio-8080-exec-17 [000094] user= 7.17% sys= 0.69% alloc= 4721kb/s - http-nio-8080-exec-14 [000092] user= 7.17% sys= 0.51% alloc= 4328kb/s - http-nio-8080-exec-12 [000081] user= 6.96% sys= 0.56% alloc= 4706kb/s - http-nio-8080-exec-7 [000076] user= 6.54% sys= 0.84% alloc= 4101kb/s - http-nio-8080-exec-2 [000082] user= 6.96% sys= 0.41% alloc= 4023kb/s - http-nio-8080-exec-8 [000095] user= 6.54% sys= 0.32% alloc= 3878kb/s - http-nio-8080-exec-15 [000079] user= 6.12% sys= 0.65% alloc= 4136kb/s - http-nio-8080-exec-5 [000084] user= 5.91% sys= 0.78% alloc= 3906kb/s - http-nio-8080-exec-10 [000075] user= 6.33% sys= 0.33% alloc= 3897kb/s - http-nio-8080-exec-1 [000078] user= 5.27% sys= 0.81% alloc= 3652kb/s - http-nio-8080-exec-4 [000080] user= 5.48% sys= 0.37% alloc= 3233kb/s - http-nio-8080-exec-6 [000083] user= 5.06% sys= 0.27% alloc= 3135kb/s - http-nio-8080-exec-9 [000077] user= 4.01% sys= 0.85% alloc= 2609kb/s - http-nio-8080-exec-3 [000098] user= 4.43% sys= 0.33% alloc= 2854kb/s - http-nio-8080-exec-18 [000024] user= 3.38% sys= 0.76% alloc= 2775kb/s - bl%004frder%0045lements.data [000093] user= 3.16% sys= 0.42% alloc= 2023kb/s - http-nio-8080-exec-13 [000101] user= 2.32% sys= 0.17% alloc= 614kb/s - RMI TCP Connection(1)-127.0.0.1 для продолжения работы нужно остановть процесс (например Ctrl-C).

    Работа с JFR из командой строки

    JFR - профайлер встроеный в OpenJDK. Воспользуется его возможностями из коммандной строки

    15 выполним команду jcmd $PID JFR.configure stackdepth=512 Stack depth: 512 данная комманда нужна чтобы полностью получать стэк-трейсы потоков нашего приложения
    16 затем выполним jcmd $PID JFR.start settings=profile filename=dump1.jfr duration=30s Started recording 1. The result will be written to: /home/boss/gigs/java-training/blf-demo/var/storefront/dump1.jfr 17 спустя 30 секунд проверим, что снятие дампа завершено jcmd $PID JFR.check No available recordings. Use jcmd 13535 JFR.start to start a recording. обратите внимание, путь к файлу дампа определяется относитель директории запуска java процесса

    OpenJDK включает консолный инструмент для работы с файлами дампов - jfr

    18 выполним команду jfr Tool for working with Flight Recorder files Before using this tool, you must have a recording file. A file can be created by starting a recording from command line: java -XX:StartFlightRecording:filename=recording.jfr,duration=30s ... A recording can also be started on already running Java Virtual Machine: jcmd (to list available pids) jcmd <pid> JFR.start Recording data can be dumped to file using the JFR.dump command: jcmd <pid> JFR.dump filename=recording.jfr The contents of the recording can then be printed, for example: jfr print recording.jfr jfr print --events CPULoad,GarbageCollection recording.jfr jfr print --json --events CPULoad recording.jfr jfr print --categories 'GC,JVM,Java*' recording.jfr jfr print --events 'jdk.*' --stack-depth 64 recording.jfr jfr summary recording.jfr jfr metadata recording.jfr jfr metadata --categories GC,Detailed For more information about available commands, use 'jfr help' 19 затем jfr summary var/storefront/dump1.jfr Version: 2.1 Chunks: 3 Start: 2024-01-23 11:27:51 (UTC) Duration: 30 s Event Type Count Size (bytes) ================================================================== jdk.ObjectAllocationSample 8720 143514 jdk.GCPhaseParallel 6860 178915 jdk.SocketRead 5786 262037 jdk.ModuleExport 5667 61827 jdk.ClassLoaderStatistics 4943 127804 jdk.ThreadPark 2237 83619 jdk.PromoteObjectInNewPLAB 2154 39989 jdk.ExecutionSample 1861 23360 jdk.BooleanFlag 1602 48993 jdk.NativeMethodSample 1315 16371 jdk.ActiveSetting 1040 34948 jdk.JavaMonitorWait 612 17926 jdk.LongFlag 594 19740 jdk.ThreadAllocationStatistics 569 6599 jdk.SocketWrite 518 21899 jdk.ModuleRequire 459 4590 jdk.UnsignedLongFlag 435 14853 jdk.CheckPoint 420 39858380 jdk.SystemProcess 372 78649 jdk.TenuringDistribution 270 3499 jdk.ThreadCPULoad 152 2593 jdk.NativeLibrary 150 10836 jdk.InitialSecurityProperty 138 10981 jdk.InitialEnvironmentVariable 129 10947 jdk.JavaMonitorEnter 120 3038 jdk.StringFlag 87 2658 jdk.MetaspaceChunkFreeListSummary 72 1440 jdk.GCReferenceStatistics 72 864 jdk.GCPhasePauseLevel1 72 3049 jdk.ThreadSleep 60 1098 jdk.PromoteObjectOutsidePLAB 59 1030 jdk.Compilation 55 1701 jdk.SafepointBegin 51 837 jdk.ExecuteVMOperation 51 927 jdk.InitialSystemProperty 45 57414 jdk.GCHeapSummary 36 1440 jdk.MetaspaceSummary 36 1908 jdk.G1HeapSummary 36 846 jdk.GCPhasePauseLevel2 35 1426 jdk.DoubleFlag 33 1329 jdk.CPULoad 29 580 jdk.JavaThreadStatistics 29 348 jdk.ClassLoadingStatistics 29 348 jdk.CompilerStatistics 29 957 jdk.ExceptionStatistics 29 463 jdk.GarbageCollection 18 432 jdk.YoungGarbageCollection 18 270 jdk.G1GarbageCollection 18 270 jdk.G1MMU 18 270 jdk.EvacuationInformation 18 522 jdk.G1EvacuationYoungStatistics 18 482 jdk.G1EvacuationOldStatistics 18 374 jdk.G1BasicIHOP 18 735 jdk.G1AdaptiveIHOP 18 738 jdk.GCPhasePause 18 450 jdk.CodeCacheStatistics 18 600 jdk.IntFlag 18 672 jdk.UnsignedIntFlag 18 618 jdk.NetworkUtilization 10 145 jdk.OldObjectSample 7 231 jdk.PhysicalMemory 6 108 jdk.CodeSweeperStatistics 6 156 jdk.GCConfiguration 6 156 jdk.DirectBufferStatistics 6 156 jdk.Deoptimization 4 108 jdk.Metadata 3 288780 jdk.ContainerConfiguration 3 218 jdk.JVMInformation 3 1281 jdk.OSInformation 3 708 jdk.VirtualizationInformation 3 108 jdk.CPUInformation 3 5088 jdk.CPUTimeStampCounter 3 60 jdk.ThreadContextSwitchRate 3 36 jdk.SymbolTableStatistics 3 117 jdk.StringTableStatistics 3 117 jdk.PlaceholderTableStatistics 3 102 jdk.LoaderConstraintsTableStatistics 3 102 jdk.ProtectionDomainCacheTableStatistics 3 102 jdk.CompilerConfiguration 3 30 jdk.CodeCacheConfiguration 3 138 jdk.CodeSweeperConfiguration 3 39 jdk.GCSurvivorConfiguration 3 33 jdk.GCTLABConfiguration 3 39 jdk.GCHeapConfiguration 3 78 jdk.YoungGenerationConfiguration 3 54 jdk.ActiveRecording 3 193 jdk.FileRead 2 111 jdk.ThreadStart 1 15 jdk.ContainerCPUUsage 1 27 jdk.ContainerCPUThrottling 1 17 jdk.ContainerMemoryUsage 1 25 jdk.ContainerIOUsage 1 22 jdk.ThreadEnd 0 0 jdk.JavaMonitorInflate 0 0 jdk.SyncOnValueBasedClass 0 0 jdk.BiasedLockRevocation 0 0 jdk.BiasedLockSelfRevocation 0 0 jdk.BiasedLockClassRevocation 0 0 jdk.ReservedStackActivation 0 0 jdk.ClassLoad 0 0 jdk.ClassDefine 0 0 jdk.ClassRedefinition 0 0 jdk.RedefineClasses 0 0 jdk.RetransformClasses 0 0 jdk.ClassUnload 0 0 jdk.IntFlagChanged 0 0 jdk.UnsignedIntFlagChanged 0 0 jdk.LongFlagChanged 0 0 jdk.UnsignedLongFlagChanged 0 0 jdk.DoubleFlagChanged 0 0 jdk.BooleanFlagChanged 0 0 jdk.StringFlagChanged 0 0 jdk.MetaspaceGCThreshold 0 0 jdk.MetaspaceAllocationFailure 0 0 jdk.MetaspaceOOM 0 0 jdk.PSHeapSummary 0 0 jdk.SystemGC 0 0 jdk.ParallelOldGarbageCollection 0 0 jdk.OldGarbageCollection 0 0 jdk.ObjectCountAfterGC 0 0 jdk.PromotionFailed 0 0 jdk.EvacuationFailed 0 0 jdk.ConcurrentModeFailure 0 0 jdk.GCPhasePauseLevel3 0 0 jdk.GCPhasePauseLevel4 0 0 jdk.GCPhaseConcurrent 0 0 jdk.GCPhaseConcurrentLevel1 0 0 jdk.AllocationRequiringGC 0 0 jdk.G1HeapRegionTypeChange 0 0 jdk.JITRestart 0 0 jdk.CompilerPhase 0 0 jdk.CompilationFailure 0 0 jdk.CompilerInlining 0 0 jdk.SweepCodeCache 0 0 jdk.CodeCacheFull 0 0 jdk.SafepointStateSynchronization 0 0 jdk.SafepointCleanup 0 0 jdk.SafepointCleanupTask 0 0 jdk.SafepointEnd 0 0 jdk.Shutdown 0 0 jdk.ObjectAllocationInNewTLAB 0 0 jdk.ObjectAllocationOutsideTLAB 0 0 jdk.DumpReason 0 0 jdk.SecurityProviderService 0 0 jdk.DataLoss 0 0 jdk.ThreadDump 0 0 jdk.ObjectCount 0 0 jdk.G1HeapRegionInformation 0 0 jdk.ZAllocationStall 0 0 jdk.ZPageAllocation 0 0 jdk.ZRelocationSet 0 0 jdk.ZRelocationSetGroup 0 0 jdk.ZStatisticsCounter 0 0 jdk.ZStatisticsSampler 0 0 jdk.ZThreadPhase 0 0 jdk.ZUncommit 0 0 jdk.ZUnmap 0 0 jdk.ShenandoahHeapRegionStateChange 0 0 jdk.ShenandoahHeapRegionInformation 0 0 jdk.Flush 0 0 jdk.HeapDump 0 0 jdk.GCLocker 0 0 jdk.Deserialization 0 0 jdk.FileForce 0 0 jdk.FileWrite 0 0 jdk.JavaExceptionThrow 0 0 jdk.JavaErrorThrow 0 0 jdk.ProcessStart 0 0 jdk.SecurityPropertyModification 0 0 jdk.TLSHandshake 0 0 jdk.X509Validation 0 0 jdk.X509Certificate 0 0 20 затем jfr print --events MethodSample,NativeMethodSample var/storefront/dump1.jfr jdk.NativeMethodSample { startTime = 14:28:18.821 sampledThread = "ProcessWatchDog" (javaThreadId = 13) state = "STATE_RUNNABLE" stackTrace = [ sun.nio.ch.Net.poll(FileDescriptor, int, long) sun.nio.ch.NioSocketImpl.park(FileDescriptor, int, long) line: 186 sun.nio.ch.NioSocketImpl.timedAccept(FileDescriptor, FileDescriptor, InetSocketAddress[], long) line: 715 sun.nio.ch.NioSocketImpl.accept(SocketImpl) line: 757 java.net.ServerSocket.implAccept(SocketImpl) line: 675 ... ] } jdk.NativeMethodSample { startTime = 14:28:18.842 sampledThread = "NioBlockingSelector.BlockPoller-1" (javaThreadId = 59) state = "STATE_RUNNABLE" stackTrace = [ sun.nio.ch.EPoll.wait(int, long, int, int) sun.nio.ch.EPollSelectorImpl.doSelect(Consumer, long) line: 118 sun.nio.ch.SelectorImpl.lockAndDoSelect(Consumer, long) line: 129 sun.nio.ch.SelectorImpl.select(long) line: 141 org.apache.tomcat.util.net.NioBlockingSelector$BlockPoller.run() line: 339 ... ] } jdk.NativeMethodSample { startTime = 14:28:18.866 sampledThread = "https-jsse-nio-8443-ClientPoller-0" (javaThreadId = 70) state = "STATE_RUNNABLE" stackTrace = [ sun.nio.ch.EPoll.wait(int, long, int, int) sun.nio.ch.EPollSelectorImpl.doSelect(Consumer, long) line: 118 sun.nio.ch.SelectorImpl.lockAndDoSelect(Consumer, long) line: 129 sun.nio.ch.SelectorImpl.select(long) line: 141 org.apache.tomcat.util.net.NioEndpoint$Poller.run() line: 785 ... ] } jdk.NativeMethodSample { startTime = 14:28:18.886 sampledThread = "https-jsse-nio-8443-ClientPoller-1" (javaThreadId = 71) state = "STATE_RUNNABLE" stackTrace = [ sun.nio.ch.EPoll.wait(int, long, int, int) sun.nio.ch.EPollSelectorImpl.doSelect(Consumer, long) line: 118 sun.nio.ch.SelectorImpl.lockAndDoSelect(Consumer, long) line: 129 sun.nio.ch.SelectorImpl.select(long) line: 141 org.apache.tomcat.util.net.NioEndpoint$Poller.run() line: 785 ... ] } ... jfr так позволяет экспортировать данные в формате JSON

    SJK позволяет строить отчёты по данным из различных источников, включая JFR

    21 выполним команду java -jar sjk.jar flame -f var/storefront/dump1.jfr -o dump1.html откройте файл dump1.html, файл может открываться несколько секунд

    Возможна так же генерация SVG формата.

    SJK может осуществлять сбор сэмплсетов на прямую, без использования JFR или других инструментов.

    22 выполним команду java -jar sjk.jar stcap -p $PID -o dump2.sjk Restarting java with unlocked package access Writing to /home/boss/gigs/java-training/blf-demo/dump2.sjk Collected 521 Collected 1043 Collected 1565 Collected 2000 Collected 2522 Collected 3044 Collected 3566 Collected 4001 Collected 4523 Collected 5045 Collected 5567 Collected 6002 Collected 6524 Collected 7046 Collected 7568 Collected 8003 Collected 8525 Collected 9047 Collected 9569 Collected 10004 Collected 10526 Collected 11048 Collected 11570 Collected 12005 Collected 12527 Collected 13049 Collected 13571 Collected 14006 Collected 14528 Collected 15050 Collected 15572 Collected 16007 Collected 16529 Collected 17051 Collected 17573 Collected 18008 Collected 18530 Collected 19052 Collected 19574 Collected 20009 Collected 20531 Collected 21053 Collected 21575 Collected 22010 Collected 22532 Collected 23054 Collected 23576 Collected 24011 Collected 24533 Collected 25055 Collected 25577 Collected 26012 Collected 26534 Collected 27056 Collected 27578 Collected 28013 Collected 28535 Collected 29057 Collected 29579 Collected 30014 Collected 30536 Collected 31058 Collected 31580 Collected 32015 Collected 32537 Collected 33059 Collected 33581 Collected 34016 Collected 34538 Collected 35060 Collected 35582 Collected 36017 Collected 36539 Collected 37061 Collected 37583 Collected 38018 Collected 38540 Collected 39062 Collected 39584 Collected 40019 Collected 40541 Collected 41063 Collected 41585 Trace dumped: 41933 23 а после её окончания java -jar sjk.jar flame -f dump2.sjk -o dump2.html откройте файл dump2.html, файл может открываться несколько секунд

    Возможна так же генерация SVG формата.

    Метод сэмплирования SJK отличается от JFR и результаты могут быть слегка дригие.

    Работа с MBean`ами

    OpenJDK включает в свой состав инструмент jconsole, который позволяет посмотреть дерево MBean`ов JVM.

    24 запустим jconsole в терминале B jconsole выберите процесс ... из списка и подключитесь

    SJK позволяет сделать полный дамп дерева MBean`ов в JSON формате.

    25 выполним команду java -jar sjk.jar mxdump -p $PID > mbeans.json файл mbeans.json содержит информацию по всем MBean`ам опубликованным JVM

    SJK так позволяет читать данные отдельных MBean`ов и их атрибутов.

    26 выполним команду java -jar sjk.jar mx -p $PID -mg -b '**:*,type=MemoryPool' -f Usage -all Restarting java with unlocked package access java.lang:name=Metaspace,type=MemoryPool Usage committed: 110034944 init: 0 max: -1 used: 109092768 java.lang:name=CodeHeap 'non-nmethods',type=MemoryPool Usage committed: 2555904 init: 2555904 max: 5836800 used: 1449088 java.lang:name=CodeHeap 'profiled nmethods',type=MemoryPool Usage committed: 64552960 init: 2555904 max: 122908672 used: 18529664 java.lang:name=Compressed Class Space,type=MemoryPool Usage committed: 12255232 init: 0 max: 1073741824 used: 11693656 java.lang:name=G1 Eden Space,type=MemoryPool Usage committed: 138412032 init: 14680064 max: -1 used: 10485760 java.lang:name=G1 Old Gen,type=MemoryPool Usage committed: 267386880 init: 243269632 max: 536870912 used: 220839424 java.lang:name=G1 Survivor Space,type=MemoryPool Usage committed: 7340032 init: 0 max: -1 used: 7317624 java.lang:name=CodeHeap 'non-profiled nmethods',type=MemoryPool Usage committed: 42467328 init: 2555904 max: 122912768 used: 42174720 27 затем java -jar sjk.jar mx -p $PID -mg -b '**:*,type=MemoryPool' -f Usage -all --csv --add-mbean-name Restarting java with unlocked package access MBean,Attribute,committed,init,max,used "java.lang:name=Metaspace,type=MemoryPool",Usage,110100480,0,-1,109114976 "java.lang:name=CodeHeap 'non-nmethods',type=MemoryPool",Usage,2555904,2555904,5836800,1449088 "java.lang:name=CodeHeap 'profiled nmethods',type=MemoryPool",Usage,64552960,2555904,122908672,18591744 "java.lang:name=Compressed Class Space,type=MemoryPool",Usage,12255232,0,1073741824,11694176 "java.lang:name=G1 Eden Space,type=MemoryPool",Usage,123731968,14680064,-1,114294784 "java.lang:name=G1 Old Gen,type=MemoryPool",Usage,281018368,243269632,536870912,233039360 "java.lang:name=G1 Survivor Space,type=MemoryPool",Usage,8388608,0,-1,8064976 "java.lang:name=CodeHeap 'non-profiled nmethods',type=MemoryPool",Usage,42467328,2555904,122912768,42078208 28 затем java -jar sjk.jar mx -p $PID -mg -b '**:*,type=MemoryPool' -f Usage -all --json-array Restarting java with unlocked package access [ {"Usage": {"committed": 110100480, "init": 0, "max": -1, "used": 109127736}}, {"Usage": {"committed": 2555904, "init": 2555904, "max": 5836800, "used": 1449088}}, {"Usage": {"committed": 64552960, "init": 2555904, "max": 122908672, "used": 18751616}}, {"Usage": {"committed": 12255232, "init": 0, "max": 1073741824, "used": 11694176}}, {"Usage": {"committed": 119537664, "init": 14680064, "max": -1, "used": 49283072}}, {"Usage": {"committed": 285212672, "init": 243269632, "max": 536870912, "used": 238071296}}, {"Usage": {"committed": 8388608, "init": 0, "max": -1, "used": 7729496}}, {"Usage": {"committed": 42467328, "init": 2555904, "max": 122912768, "used": 42163328}} ] мы получили аттрибьют "Usage" с MBean`ов отвечающих на пулы памяти JVM, в различных форматах.

    SJK так позволяет менят значение атрибьютов MBean`ов, для которых, такая операция доступна.

    29 выполним команду java -jar sjk.jar mx -p $PID -mg -b '**:*,type=Connector,port=8080' -all -f maxThreads Restarting java with unlocked package access Tomcat:type=Connector,port=8080 maxThreads 200 30 зафиксируем текущее значение, затем выполним java -jar sjk.jar mx -p $PID -ms -b '**:*,type=Connector,port=8080' -f maxThreads -v 100 Restarting java with unlocked package access Tomcat:type=Connector,port=8080 31 затем java -jar sjk.jar mx -p $PID -mg -b '**:*,type=Connector,port=8080' -all -f maxThreads Restarting java with unlocked package access Tomcat:type=Connector,port=8080 maxThreads 100 мы можем убедиться, что значение аттрибьюта было изменено.

    Дамп памяти и гистограмы классов

    Иногда для диагностики, нам необходимо проанализировать память Java процесса.

    Дамп памяти JVM можно получить с помощью комманды jcmd или jmap

    32 выполним команду jcmd $PID help GC.heap_dump GC.heap_dump Generate a HPROF format dump of the Java heap. Impact: High: Depends on Java heap size and content. Request a full GC unless the '-all' option is specified. Permission: java.lang.management.ManagementPermission(monitor) Syntax : GC.heap_dump [options] <filename> Arguments: filename : Name of the dump file (STRING, no default value) Options: (options must be specified using the <key> or <key>=<value> syntax) -all : [optional] Dump all objects, including unreachable objects (BOOLEAN, false) -gz : [optional] If specified, the heap dump is written in gzipped format using the given compression level. 1 (recommended) is the fastest, 9 the strongest compression. (INT, 1) -overwrite : [optional] If specified, the dump file will be overwritten if it exists (BOOLEAN, false) 33 затем jcmd $PID GC.heap_dump -all -gz=1 -overwrite appdump.hprof.gz Dumping heap to appdump.hprof.gz ... Heap dump file created [71822848 bytes in 2.017 secs] Файл записывается относительно директории запуска приложения. В наше случае var/storefront.

    Для работы с дампом нужны дополнительные инструменты. Иногда бывает полезно взглянуть на гистограму классов.

    34 выполним команду jcmd $PID help GC.class_histogram GC.class_histogram Provide statistics about the Java heap usage. Impact: High: Depends on Java heap size and content. Permission: java.lang.management.ManagementPermission(monitor) Syntax : GC.class_histogram [options] Options: (options must be specified using the <key> or <key>=<value> syntax) -all : [optional] Inspect all objects, including unreachable objects (BOOLEAN, false) -parallel : [optional] Number of parallel threads to use for heap inspection. 0 (the default) means let the VM determine the number of threads to use. 1 means use one thread (disable parallelism). For any other value the VM will try to use the specified number of threads, but might use fewer. (INT, 0) 35 затем jcmd $PID GC.class_histogram num #instances #bytes class name (module) ------------------------------------------------------- 1: 264074 25506808 [B (java.base@17.0.9) 2: 193454 6190528 java.util.HashMap$Node (java.base@17.0.9) 3: 253077 6073848 java.lang.String (java.base@17.0.9) 4: 68005 5984440 java.lang.reflect.Method (java.base@17.0.9) 5: 110832 4433280 java.util.LinkedHashMap$Entry (java.base@17.0.9) 6: 43121 4088248 [Ljava.util.HashMap$Node; (java.base@17.0.9) 7: 91774 3670960 java.util.TreeMap$Entry (java.base@17.0.9) 8: 102365 3275680 java.util.concurrent.ConcurrentHashMap$Node (java.base@17.0.9) 9: 58198 2659944 [Ljava.lang.Object; (java.base@17.0.9) 10: 99245 2362368 [Ljava.lang.String; (java.base@17.0.9) 11: 19213 2308736 java.lang.Class (java.base@17.0.9) 12: 40132 2247392 java.util.LinkedHashMap (java.base@17.0.9) 13: 24172 1933760 net.sf.ehcache.Element 14: 6155 1905000 [C (java.base@17.0.9) 15: 15930 1653504 [I (java.base@17.0.9) 16: 59308 1423392 java.lang.Long (java.base@17.0.9) 17: 28326 1359648 java.util.TreeMap (java.base@17.0.9) 18: 1537 1293040 [Ljava.util.concurrent.ConcurrentHashMap$Node; (java.base@17.0.9) 19: 26725 1282800 java.util.HashMap (java.base@17.0.9) 20: 20637 1155672 net.sf.ehcache.store.disk.DiskStorageFactory$DiskMarker 21: 20147 807880 [Ljava.io.Serializable; (java.base@17.0.9) 22: 33376 801024 java.util.ArrayList (java.base@17.0.9) 23: 36088 765776 [Ljava.lang.Class; (java.base@17.0.9) 24: 22100 707200 net.sf.ehcache.util.concurrent.ConcurrentHashMap$Node 25: 21714 694848 java.util.Hashtable$Entry (java.base@17.0.9) 26: 42902 686432 java.lang.Object (java.base@17.0.9) 27: 28287 678888 org.springframework.security.access.method.DelegatingMethodSecurityMetadataSource$DefaultCacheKey 28: 28084 674016 javax.management.openmbean.CompositeDataSupport (java.management@17.0.9) 29: 20638 660416 net.sf.ehcache.store.disk.HashEntry 30: 20478 655296 org.hibernate.cache.spi.CacheKey 31: 8483 610776 java.lang.reflect.Field (java.base@17.0.9) 32: 18425 589600 antlr.ANTLRHashString 33: 29538 472608 java.lang.Integer (java.base@17.0.9) 34: 28106 449696 java.util.TreeMap$KeySet (java.base@17.0.9) 35: 18469 443256 org.springframework.core.MethodClassKey 36: 12678 405696 java.lang.ref.WeakReference (java.base@17.0.9) 37: 7975 398592 [[Ljava.lang.String; (java.base@17.0.9) 38: 7924 380352 net.sf.ehcache.store.disk.ods.Region 39: 9465 378600 java.lang.ref.SoftReference (java.base@17.0.9) 40: 7789 373872 org.hibernate.hql.internal.ast.tree.Node 41: 11481 367392 java.util.LinkedList (java.base@17.0.9) 42: 3729 357984 org.springframework.beans.GenericTypeAwarePropertyDescriptor 43: 5352 342528 java.util.concurrent.ConcurrentHashMap (java.base@17.0.9) 44: 14093 338232 java.util.Collections$UnmodifiableRandomAccessList (java.base@17.0.9) 45: 4672 336384 java.lang.reflect.Constructor (java.base@17.0.9) 46: 20825 333200 java.util.concurrent.atomic.AtomicBoolean (java.base@17.0.9) 47: 13733 329592 java.util.Arrays$ArrayList (java.base@17.0.9) 48: 6087 292176 java.util.concurrent.locks.ReentrantReadWriteLock$NonfairSync (java.base@17.0.9) 49: 7047 281880 org.terracotta.statistics.archive.StatisticSampler 50: 1280 243584 [Lnet.sf.ehcache.store.disk.HashEntry; 51: 4277 239512 org.hibernate.cache.spi.QueryKey 52: 7304 233728 org.hibernate.cache.ehcache.internal.strategy.AbstractReadWriteEhcacheAccessStrategy$Item 53: 9737 233688 java.beans.MethodRef (java.desktop@17.0.9) 54: 9564 229536 org.hibernate.engine.spi.TypedValue 55: 7081 226592 org.hibernate.cache.spi.entry.CacheEntry 56: 5491 219640 org.hibernate.loader.DefaultEntityAliases 57: 13455 215280 java.util.LinkedHashSet (java.base@17.0.9) 58: 7946 213200 [Z (java.base@17.0.9) 59: 8711 209064 sun.reflect.annotation.AnnotationInvocationHandler (java.base@17.0.9) 60: 13060 208960 org.hibernate.cache.spi.entry.CollectionCacheEntry 61: 4264 204672 org.hibernate.cfg.annotations.reflection.JPAOverriddenAnnotationReader 62: 226 179856 [J (java.base@17.0.9) 63: 7402 177648 java.util.concurrent.CopyOnWriteArrayList (java.base@17.0.9) 64: 7047 169128 net.sf.ehcache.statistics.extended.SampledStatistic 65: 7047 169128 org.terracotta.statistics.archive.StatisticArchive 66: 7047 169128 org.terracotta.statistics.archive.StatisticSampler$SamplingTask 67: 2988 167328 org.thymeleaf.engine.Text 68: 2944 164864 net.sf.ehcache.store.chm.SelectableConcurrentHashMap$Segment 69: 965 164080 [Ljava.util.Hashtable$Entry; (java.base@17.0.9) 70: 1015 162400 org.springframework.beans.factory.support.RootBeanDefinition 71: 2475 158400 org.springframework.core.annotation.AnnotationAttributes 72: 4942 158144 org.hibernate.annotations.common.reflection.java.JavaXSimpleType 73: 1620 155520 org.hibernate.loader.entity.EntityLoader 74: 3804 152160 java.math.BigInteger (java.base@17.0.9) 75: 2371 151744 org.springframework.core.MethodParameter 76: 3118 149664 org.hibernate.engine.spi.CollectionEntry 77: 2982 143136 org.thymeleaf.engine.Attribute 78: 3535 141400 net.sf.ehcache.store.chm.SelectableConcurrentHashMap$HashEntry 79: 2488 139328 org.hibernate.collection.internal.PersistentBag 80: 4277 136864 org.hibernate.transform.CacheableResultTransformer 81: 4259 136288 org.terracotta.statistics.jsr166e.LongAdder 82: 3340 133600 com.sun.beans.util.Cache$Kind$Soft (java.desktop@17.0.9) 83: 4168 133376 java.util.RegularEnumSet (java.base@17.0.9) 84: 5404 129696 org.hibernate.annotations.common.reflection.java.JavaReflectionManager$MemberKey 85: 5335 128040 java.util.LinkedList$Node (java.base@17.0.9) 86: 3105 124200 org.hibernate.engine.spi.CollectionKey 87: 5061 121464 java.util.Date (java.base@17.0.9) 88: 2980 119200 java.math.BigDecimal (java.base@17.0.9) 89: 4960 119040 sun.reflect.generics.tree.SimpleClassTypeSignature (java.base@17.0.9) 90: 7272 116352 java.util.LinkedHashMap$LinkedKeySet (java.base@17.0.9) ... 7990: 1 16 sun.security.ssl.ServerHello$T13HelloRetryRequestProducer (java.base@17.0.9) 7991: 1 16 sun.security.ssl.ServerHello$T13HelloRetryRequestReproducer (java.base@17.0.9) 7992: 1 16 sun.security.ssl.ServerHello$T13ServerHelloProducer (java.base@17.0.9) 7993: 1 16 sun.security.ssl.ServerHelloDone$ServerHelloDoneConsumer (java.base@17.0.9) 7994: 1 16 sun.security.ssl.ServerHelloDone$ServerHelloDoneProducer (java.base@17.0.9) 7995: 1 16 sun.security.ssl.ServerKeyExchange$ServerKeyExchangeConsumer (java.base@17.0.9) 7996: 1 16 sun.security.ssl.ServerKeyExchange$ServerKeyExchangeProducer (java.base@17.0.9) 7997: 1 16 sun.security.util.ByteArrayLexOrder (java.base@17.0.9) 7998: 1 16 sun.security.util.ByteArrayTagOrder (java.base@17.0.9) 7999: 1 16 sun.security.util.KeyStoreDelegator$$Lambda$141/0x00007fbd40853c60 (java.base@17.0.9) 8000: 1 16 sun.util.calendar.Gregorian (java.base@17.0.9) 8001: 1 16 sun.util.calendar.JulianCalendar (java.base@17.0.9) 8002: 1 16 sun.util.cldr.CLDRBaseLocaleDataMetaInfo (java.base@17.0.9) 8003: 1 16 sun.util.cldr.CLDRLocaleProviderAdapter$$Lambda$57/0x80000005e (java.base@17.0.9) 8004: 1 16 sun.util.locale.InternalLocaleBuilder$CaseInsensitiveChar (java.base@17.0.9) 8005: 1 16 sun.util.locale.provider.CalendarDataUtility$CalendarFieldValueNamesMapGetter (java.base@17.0.9) 8006: 1 16 sun.util.locale.provider.CalendarDataUtility$CalendarWeekParameterGetter (java.base@17.0.9) 8007: 1 16 sun.util.locale.provider.CalendarNameProviderImpl$LengthBasedComparator (java.base@17.0.9) 8008: 1 16 sun.util.locale.provider.TimeZoneNameUtility$TimeZoneNameGetter (java.base@17.0.9) 8009: 1 16 sun.util.logging.PlatformLogger (java.base@17.0.9) 8010: 1 16 sun.util.logging.internal.LoggingProviderImpl (java.logging@17.0.9) 8011: 1 16 sun.util.resources.LocaleData$LocaleDataStrategy (java.base@17.0.9) 8012: 1 16 sun.util.resources.cldr.provider.CLDRLocaleDataMetaInfo (jdk.localedata@17.0.9) Total 2697492 116703832

    SJK позволяет получить дополнительны типы гистограм классов, например гистограмму "мёртвых" объектов.

    36 выполним команду java -jar sjk.jar hh --dead -n 100 -p $PID # Instances Bytes Type 1: 60664 2426560 org.hsqldb.ColumnBase 2: 40896 1963008 org.springframework.core.ResolvableType 3: 5249 1436584 [Lorg.thymeleaf.engine.IEngineTemplateEvent; 4: 21247 1189832 org.hsqldb.types.CharacterType 5: 21040 1009920 org.thymeleaf.engine.Attribute 6: 17384 973504 org.thymeleaf.engine.Text 7: 19844 952512 org.thymeleaf.engine.OpenElementTag 8: 21775 871000 org.hibernate.engine.spi.CollectionKey 9: 32927 790248 org.springframework.expression.TypedValue 10: 5838 747264 org.hsqldb.result.Result 11: 19715 658944 [Lorg.thymeleaf.processor.element.IElementProcessor; 12: 24316 583584 org.springframework.core.convert.TypeDescriptor 13: 24316 583584 org.springframework.core.convert.TypeDescriptor$AnnotatedElementAdapter 14: 19188 510792 [Lorg.thymeleaf.engine.Attribute; 15: 10545 506160 org.thymeleaf.engine.ElementProcessorIterator 16: 10126 486048 org.hibernate.engine.spi.CollectionEntry 17: 19538 468912 org.thymeleaf.engine.Attributes 18: 8262 462672 org.hibernate.collection.internal.PersistentBag 19: 7214 461696 org.springframework.core.MethodParameter 20: 18829 451896 org.hibernate.internal.util.collections.IdentityMap$IdentityKey 21: 9245 443760 org.hibernate.engine.spi.EntityKey 22: 11076 443040 org.springframework.expression.spel.ExpressionState 23: 5789 416808 org.hibernate.engine.spi.EntityEntry 24: 8623 413904 org.thymeleaf.engine.CloseElementTag 25: 16598 398352 org.springframework.expression.spel.support.ReflectivePropertyAccessor$PropertyCacheKey 26: 4783 382640 net.sf.ehcache.Element 27: 22923 366768 org.springframework.core.ResolvableType$DefaultVariableResolver 28: 11370 363840 org.thymeleaf.cache.ExpressionCacheKey 29: 7298 350304 org.hsqldb.types.NumberType 30: 10545 337440 org.thymeleaf.engine.ProcessorExecutionVars 31: 3407 309368 [Lorg.hsqldb.types.Type; 32: 2635 287744 [Lorg.hsqldb.ColumnBase; 33: 8443 270176 org.hibernate.cache.spi.CacheKey 34: 11152 267648 org.hibernate.internal.util.collections.IdentityMap$IdentityMapEntry 35: 8205 262560 org.springframework.core.SerializableTypeWrapper$MethodParameterTypeProvider 36: 4532 217536 net.sf.ehcache.store.disk.ods.Region 37: 6703 214496 net.sf.ehcache.store.disk.HashEntry 38: 8612 206688 org.hibernate.type.AbstractStandardBasicType$1 39: 8474 203376 org.springframework.expression.spel.support.ReflectivePropertyAccessor$OptimalPropertyAccessor 40: 4177 200496 org.hsqldb.result.ResultMetaData 41: 3465 194040 net.sf.ehcache.store.disk.DiskStorageFactory$DiskMarker 42: 7839 188136 org.hibernate.engine.spi.TypedValue 43: 7656 183744 org.thymeleaf.spring4.expression.SPELContextMapWrapper 44: 5477 175264 net.sf.ehcache.util.concurrent.ConcurrentHashMap$Node 45: 3467 166416 org.thymeleaf.engine.StandaloneElementTag 46: 3982 159280 org.hibernate.event.spi.LoadEvent 47: 4945 158240 org.hibernate.LockOptions 48: 4714 150848 org.hibernate.engine.internal.Cascade 49: 4421 141472 org.thymeleaf.engine.Model 50: 5730 137520 org.springframework.core.SerializableTypeWrapper$2 51: 5657 135768 org.springframework.core.convert.support.GenericConversionService$ConverterCacheKey 52: 5515 132360 net.sf.ehcache.store.CacheStore$4 53: 1489 131032 org.hibernate.engine.spi.QueryParameters 54: 2325 130200 org.hibernate.ejb.criteria.path.SingularAttributePath 55: 3973 127136 org.springframework.expression.spel.ast.PropertyOrFieldReference$AccessorLValue 56: 2990 119600 org.hibernate.ejb.criteria.expression.PathTypeExpression 57: 4839 116136 org.hibernate.collection.internal.AbstractPersistentCollection$IteratorProxy 58: 4788 114912 org.broadleafcommerce.common.money.Money 59: 1657 106048 org.hibernate.collection.internal.PersistentMap 60: 774 105264 org.hsqldb.jdbc.JDBCPreparedStatement 61: 1863 104328 org.hsqldb.navigator.RowSetNavigatorClient 62: 2410 96400 org.hibernate.ejb.criteria.expression.LiteralExpression 63: 891 92664 org.hibernate.internal.QueryImpl 64: 3744 89856 org.broadleafcommerce.common.extension.ExtensionResultHolder 65: 1595 89320 org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation 66: 2790 89280 org.hibernate.type.descriptor.sql.BigIntTypeDescriptor$2 67: 2761 88352 org.springframework.beans.BeanWrapperImpl$BeanPropertyHandler 68: 2672 85504 net.sf.ehcache.store.cachingtier.OnHeapCachingTier$Fault 69: 3546 85104 org.thymeleaf.standard.expression.ExpressionParsingNode 70: 1725 82800 org.hibernate.ejb.criteria.predicate.ComparisonPredicate 71: 3110 81544 [Lorg.springframework.core.ResolvableType; 72: 2488 79616 org.hibernate.engine.query.spi.QueryPlanCache$HQLQueryPlanKey 73: 3088 74112 org.springframework.aop.framework.AdvisedSupport$MethodCacheKey 74: 2310 73920 org.springframework.expression.spel.ast.MethodReference$MethodValueRef 75: 2305 73760 org.hibernate.type.descriptor.sql.VarcharTypeDescriptor$2 76: 2286 73152 org.hibernate.ejb.criteria.CriteriaQueryCompiler$1$1 77: 1139 72896 net.sf.ehcache.util.PreferredLoaderObjectInputStream 78: 1771 70840 org.springframework.core.SerializableTypeWrapper$MethodInvokeTypeProvider 79: 1095 70080 org.thymeleaf.engine.Comment 80: 2124 67968 org.hibernate.event.spi.PostLoadEvent 81: 2777 66648 org.hibernate.ejb.QueryImpl$ParameterImpl 82: 1958 62656 org.hibernate.cache.ehcache.internal.strategy.AbstractReadWriteEhcacheAccessStrategy$Item 83: 1490 59600 org.hibernate.event.spi.FlushEntityEvent 84: 530 59360 org.broadleafcommerce.core.catalog.domain.ProductImpl 85: 337 59312 org.broadleafcommerce.core.catalog.domain.CategoryImpl 86: 1825 58400 org.hibernate.cache.spi.entry.CacheEntry 87: 378 57456 org.broadleafcommerce.core.catalog.domain.SkuImpl 88: 1009 56504 org.hibernate.cache.spi.QueryKey 89: 2351 56424 org.hibernate.event.spi.PersistEvent 90: 703 56240 org.hsqldb.jdbc.JDBCResultSet 91: 1386 55440 org.springframework.web.context.request.ServletWebRequest 92: 550 52800 org.thymeleaf.engine.IteratedGatheringModelProcessable 93: 891 49896 org.hibernate.ejb.QueryImpl 94: 306 48960 org.broadleafcommerce.core.order.domain.DiscreteOrderItemImpl 95: 1516 48512 org.thymeleaf.cache.StandardCache$CacheEntry 96: 1177 47080 net.sf.ehcache.store.disk.DiskStorageFactory$Placeholder 97: 1470 47040 org.springframework.expression.spel.standard.Token 98: 2505 45392 [Lorg.hibernate.type.Type; 99: 895 42960 org.springframework.expression.spel.ast.PropertyOrFieldReference 100: 1762 42288 org.springframework.beans.AbstractNestablePropertyAccessor$PropertyTokenHolder Total 830075 32242064 комманда hh также есть возможность ограничить размер гистограмы.

    Завершим работу тестового стенда.

    37 Удалите директорию LABDIR/blf-demo/pids (например rm -rf pids).
    Остановите jconsole в терминале B.
    Проверьте выполняющиеся java процессы с помощью jcmd и остановие процессы демострационного стенда если они попрежнему выполняются.

    Работа с контейнером

    Запустим демонстрационный стэнд в режиме контейнера.

    38 в директории LABDIR/blf-demo выполним команду mvn -P build_image,run_n_load_docker package Команда требует значительного времени для запуска окружения. Сборка должна завершиться успешно.

    Проверим доступность приложения по ссылке http://127.0.0.1:8080.

    Удостоверимся, что контейнер запущен командой docker ps.

    Выполним листинг java процессов.

    39 выполним команду jcmd 20807 info.ragozin.hsql.HsqlStarter 20840 info.ragozin.solr.SolrStarter 21355 info.ragozin.loadgen.LoadGenStarter 21468 jdk.jcmd/sun.tools.jcmd.JCmd в списке отсутсвует процесс прилежения (который сейчас запущен в контейнере).

    40 Если у вас Linux, перезапустите jcmd под root sudo $JAVA_HOME/bin/jcmd 20807 info.ragozin.hsql.HsqlStarter 20840 info.ragozin.solr.SolrStarter 21355 info.ragozin.loadgen.LoadGenStarter 21551 jdk.jcmd/sun.tools.jcmd.JCmd 21039 com.community.SiteApplication теперь процесс приложения должен быть в списке.

    Другие операции jcmd так же доступны с хоста. Например sudo $JAVA_HOME/bin/jcmd $PID Thread.print позволяет получить дамп потоков.

    Зайдём в контейнер используя консоль B

    41 Выполните команду docker exec -it storefront bash затем в консоли контейнера jcmd 145 jdk.jcmd/sun.tools.jcmd.JCmd 1 com.community.SiteApplication изнутри мы видим 2 процесса jcmd и процесс приложения с PID 1.

    Для удалённого доступа диагностического инструментария к процессу в контейнере мы должно открыть порт JMX агента.

    42 В консоли контейнера выполните jcmd 1 ManagementAgent.start jmxremote.authenticate=false jmxremote.ssl=false jmxremote.port=11122 jmxremote.rmi.port=11122 данная команда стартует JMX агент на порте 11122.

    Данный порт уже опубликован в комманде запуска контейнера (в Docker порт не может быть опубликован динамически, но в Kubernetes есть комманда port-forward).

    В терминале B завершите сессию в контейнере коммнадой exit.

    Проверим доступность JMX end point для подключения из вне.

    43 выполните комманду java -jar sjk.jar mxping -s 127.0.0.1:11222 SJK is running on: OpenJDK 64-Bit Server VM 17.0.9+9 (Eclipse Adoptium) Java home: /home/boss/gigs/java-training/jdk/jdk-17.0.9+9 Try to connect via TLS Establishing connection to 127.0.0.1:11222 Failed to connect using TLS: java.rmi.ConnectIOException: error during JRMP connection establishment; nested exception is: javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake Try to use plain socket Establishing connection to 127.0.0.1:11222 Establishing connection to 127.2.2.2:11122 JMX Connection failed: java.rmi.ConnectException: Connection refused to host: 127.2.2.2; nested exception is: java.net.ConnectException: Connection refused тестовое соединение не проходит из-за несоответсвия сетевых адресов.

    44 повторим комманду с ключём --force-address java -jar sjk.jar mxping -s 127.0.0.1:11222 --force-address SJK is running on: OpenJDK 64-Bit Server VM 17.0.9+9 (Eclipse Adoptium) Java home: /home/boss/gigs/java-training/jdk/jdk-17.0.9+9 Try to connect via TLS Establishing connection to 127.0.0.1:11222 Failed to connect using TLS: java.rmi.ConnectIOException: error during JRMP connection establishment; nested exception is: javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake Try to use plain socket Establishing connection to 127.0.0.1:11222 Establishing connection to 127.0.0.1:11222 (overriden from 127.2.2.2:11122) Establishing connection to 127.0.0.1:11222 (overriden from 127.2.2.2:11122) Remote VM: OpenJDK 64-Bit Server VM 17.0.9+9 (Eclipse Adoptium) Теперь тестовое соединение работает, SJK имеет модифицированный JXM стэк для решение подобных проблем.

    Команда mprx, доступная в SJK, позволяет запустить локальный прокси для JMX протокола.

    45 Выполните команду в консоли B из директории LABDIR/blf-demo java -jar sjk.jar mprx -s 127.0.0.1:11222 --force-address -b 127.0.0.1:5555 Connected to target JMX endpoint Open proxy JMX end point on URI - service:jmx:rmi://127.0.0.1:5555/jmxrmi JMX proxy is running - 127.0.0.1:5555 Interrupt this command to kill proxy Прокси будет работать пока процесс не будет остановлен.

    Проверим работу через прокси.

    46 Запустим ttop через прокси. java -jar sjk.jar ttop -s 127.0.0.1:5555 Monitoring threads ... 2024-01-23T16:10:28.223+0300 Process summary process cpu=55.50% application cpu=3.49% (user=2.87% sys=0.62%) other: cpu=52.00% thread count: 180 heap allocation rate 1072kb/s [000200] user= 2.68% sys= 0.56% alloc= 1006kb/s - RMI TCP Connection(11)-172.17.0.1 [000202] user= 0.00% sys= 0.07% alloc= 1249b/s - JMX server connection timeout 202 [000013] user= 0.19% sys=-0.14% alloc= 63kb/s - ProcessWatchDog [000052] user= 0.00% sys= 0.01% alloc= 0b/s - rebuildIndexScheduler_Worker-7 [000048] user= 0.00% sys= 0.01% alloc= 0b/s - rebuildIndexScheduler_Worker-3 [000085] user= 0.00% sys= 0.01% alloc= 53b/s - http-nio-8080-ClientPoller-0 [000047] user= 0.00% sys= 0.01% alloc= 0b/s - rebuildIndexScheduler_Worker-2 [000055] user= 0.00% sys= 0.01% alloc= 0b/s - rebuildIndexScheduler_Worker-10 [000071] user= 0.00% sys= 0.01% alloc= 64b/s - https-jsse-nio-8443-ClientPoller-1 [000050] user= 0.00% sys= 0.01% alloc= 0b/s - rebuildIndexScheduler_Worker-5 [000059] user= 0.00% sys= 0.01% alloc= 0b/s - NioBlockingSelector.BlockPoller-1 [000053] user= 0.00% sys= 0.01% alloc= 0b/s - rebuildIndexScheduler_Worker-8 [000086] user= 0.00% sys= 0.01% alloc= 53b/s - http-nio-8080-ClientPoller-1 [000056] user= 0.00% sys= 0.01% alloc= 36b/s - rebuildIndexScheduler_QuartzSchedulerThread [000074] user= 0.00% sys= 0.01% alloc= 0b/s - NioBlockingSelector.BlockPoller-2 [000054] user= 0.00% sys= 0.01% alloc= 0b/s - rebuildIndexScheduler_Worker-9 [000088] user= 0.00% sys= 0.01% alloc= 53b/s - http-nio-8080-AsyncTimeout [000049] user= 0.00% sys= 0.01% alloc= 0b/s - rebuildIndexScheduler_Worker-4 [000070] user= 0.00% sys= 0.01% alloc= 64b/s - https-jsse-nio-8443-ClientPoller-0 [000043] user= 0.00% sys= 0.01% alloc= 1079b/s - ContainerBackgroundProcessor[StandardEngine[Tomcat]] Остановите команду после получения результата.

    Так же мы можем использовать функционал jcmd через JMX прокси.

    47 Зарустите команду java -jar sjk.jar jcmd -s 127.0.0.1:5555 -c help The following commands are available: Compiler.CodeHeap_Analytics Compiler.codecache Compiler.codelist Compiler.directives_add Compiler.directives_clear Compiler.directives_print Compiler.directives_remove Compiler.perfmap Compiler.queue GC.class_histogram GC.finalizer_info GC.heap_info GC.run GC.run_finalization JFR.check JFR.configure JFR.dump JFR.start JFR.stop JVMTI.agent_load JVMTI.data_dump System.trim_native_heap Thread.print VM.cds VM.class_hierarchy VM.classloader_stats VM.classloaders VM.command_line VM.dynlibs VM.events VM.flags VM.info VM.log VM.metaspace VM.native_memory VM.print_touched_methods VM.set_flag VM.stringtable VM.symboltable VM.system_properties VM.systemdictionary VM.uptime VM.version help 48 затем java -jar sjk.jar jcmd -s 127.0.0.1:5555 -c Thread.print "http-nio-8080-exec-116" #209 daemon prio=5 os_prio=0 cpu=33.38ms elapsed=124.75s tid=0x00007f197c041320 nid=0xf9 waiting on condition [0x00007f192520e000] java.lang.Thread.State: TIMED_WAITING (parking) at jdk.internal.misc.Unsafe.park(java.base@17.0.9/Native Method) - parking to wait for <0x00000000f85af2a8> (a java.util.concurrent.CountDownLatch$Sync) at java.util.concurrent.locks.LockSupport.parkNanos(java.base@17.0.9/LockSupport.java:252) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(java.base@17.0.9/AbstractQueuedSynchronizer.java:717) at java.util.concurrent.locks.AbstractQueuedSynchronizer.tryAcquireSharedNanos(java.base@17.0.9/AbstractQueuedSynchronizer.java:1074) at java.util.concurrent.CountDownLatch.await(java.base@17.0.9/CountDownLatch.java:276) at org.apache.tomcat.jdbc.pool.FairBlockingQueue.poll(FairBlockingQueue.java:153) at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:682) at org.apache.tomcat.jdbc.pool.ConnectionPool.getConnection(ConnectionPool.java:198) at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:132) at org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider.getConnection(InjectedDataSourceConnectionProvider.java:70) at org.hibernate.internal.AbstractSessionImpl$NonContextualJdbcConnectionAccess.obtainConnection(AbstractSessionImpl.java:292) at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.obtainConnection(LogicalConnectionImpl.java:297) at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.getConnection(LogicalConnectionImpl.java:169) at org.hibernate.engine.jdbc.internal.proxy.ConnectionProxyHandler.extractPhysicalConnection(ConnectionProxyHandler.java:82) at org.hibernate.engine.jdbc.internal.proxy.ConnectionProxyHandler.continueInvocation(ConnectionProxyHandler.java:138) at org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81) at jdk.proxy2.$Proxy243.prepareStatement(jdk.proxy2/Unknown Source) at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$5.doPrepare(StatementPreparerImpl.java:147) at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:166) at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:145) at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1854) at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1831) at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1811) at org.hibernate.loader.Loader.doQuery(Loader.java:899) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:341) at org.hibernate.loader.Loader.doList(Loader.java:2516) at org.hibernate.loader.Loader.listUsingQueryCache(Loader.java:2361) at org.hibernate.loader.Loader.list(Loader.java:2324) at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:490) at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:355) at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:195) at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1247) at org.hibernate.internal.QueryImpl.list(QueryImpl.java:101) at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:264) at org.broadleafcommerce.common.currency.dao.BroadleafCurrencyDaoImpl.findDefaultBroadleafCurrency(BroadleafCurrencyDaoImpl.java:49) at org.broadleafcommerce.common.currency.dao.BroadleafCurrencyDaoImpl$$FastClassBySpringCGLIB$$a820f414.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:738) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:673) at org.broadleafcommerce.common.currency.dao.BroadleafCurrencyDaoImpl$$EnhancerBySpringCGLIB$$6c4cbe9c.findDefaultBroadleafCurrency(<generated>) at org.broadleafcommerce.common.currency.service.BroadleafCurrencyServiceImpl.findDefaultBroadleafCurrency(BroadleafCurrencyServiceImpl.java:47) at org.broadleafcommerce.common.currency.service.BroadleafCurrencyServiceImpl$$FastClassBySpringCGLIB$$6e082cf4.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:669) at org.broadleafcommerce.common.currency.service.BroadleafCurrencyServiceImpl$$EnhancerBySpringCGLIB$$f35d7848.findDefaultBroadleafCurrency(<generated>) at org.broadleafcommerce.common.web.BroadleafCurrencyResolverImpl.resolveCurrency(BroadleafCurrencyResolverImpl.java:98) at org.broadleafcommerce.common.web.BroadleafRequestProcessor.process(BroadleafRequestProcessor.java:138) at org.broadleafcommerce.common.web.BroadleafRequestFilter.doFilterInternalUnlessIgnored(BroadleafRequestFilter.java:109) at org.broadleafcommerce.common.web.filter.AbstractIgnorableOncePerRequestFilter.doFilterInternal(AbstractIgnorableOncePerRequestFilter.java:58) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:178) at org.broadleafcommerce.common.web.filter.IgnorableOpenEntityManagerInViewFilter.doFilterInternal(IgnorableOpenEntityManagerInViewFilter.java:54) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.broadleafcommerce.common.web.filter.SecurityBasedIgnoreFilter.doFilter(SecurityBasedIgnoreFilter.java:77) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) - locked <0x00000000f7ebf170> (a org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper) at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@17.0.9/ThreadPoolExecutor.java:1136) at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@17.0.9/ThreadPoolExecutor.java:635) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(java.base@17.0.9/Thread.java:840) "http-nio-8080-exec-117" #210 daemon prio=5 os_prio=0 cpu=26.24ms elapsed=124.48s tid=0x00007f19800455b0 nid=0xfa waiting on condition [0x00007f192510e000] java.lang.Thread.State: TIMED_WAITING (parking) at jdk.internal.misc.Unsafe.park(java.base@17.0.9/Native Method) - parking to wait for <0x00000000f878d3e0> (a java.util.concurrent.CountDownLatch$Sync) at java.util.concurrent.locks.LockSupport.parkNanos(java.base@17.0.9/LockSupport.java:252) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(java.base@17.0.9/AbstractQueuedSynchronizer.java:717) at java.util.concurrent.locks.AbstractQueuedSynchronizer.tryAcquireSharedNanos(java.base@17.0.9/AbstractQueuedSynchronizer.java:1074) at java.util.concurrent.CountDownLatch.await(java.base@17.0.9/CountDownLatch.java:276) at org.apache.tomcat.jdbc.pool.FairBlockingQueue.poll(FairBlockingQueue.java:153) at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:682) at org.apache.tomcat.jdbc.pool.ConnectionPool.getConnection(ConnectionPool.java:198) at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:132) at org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider.getConnection(InjectedDataSourceConnectionProvider.java:70) at org.hibernate.internal.AbstractSessionImpl$NonContextualJdbcConnectionAccess.obtainConnection(AbstractSessionImpl.java:292) at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.obtainConnection(LogicalConnectionImpl.java:297) at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.getConnection(LogicalConnectionImpl.java:169) at org.hibernate.engine.jdbc.internal.proxy.ConnectionProxyHandler.extractPhysicalConnection(ConnectionProxyHandler.java:82) at org.hibernate.engine.jdbc.internal.proxy.ConnectionProxyHandler.continueInvocation(ConnectionProxyHandler.java:138) at org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81) at jdk.proxy2.$Proxy243.prepareStatement(jdk.proxy2/Unknown Source) at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$5.doPrepare(StatementPreparerImpl.java:147) at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:166) at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:145) at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1854) at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1831) at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1811) at org.hibernate.loader.Loader.doQuery(Loader.java:899) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:341) at org.hibernate.loader.Loader.doList(Loader.java:2516) at org.hibernate.loader.Loader.listUsingQueryCache(Loader.java:2361) at org.hibernate.loader.Loader.list(Loader.java:2324) at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:490) at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:355) at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:195) at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1247) at org.hibernate.internal.QueryImpl.list(QueryImpl.java:101) at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:264) at org.broadleafcommerce.common.currency.dao.BroadleafCurrencyDaoImpl.findDefaultBroadleafCurrency(BroadleafCurrencyDaoImpl.java:49) at org.broadleafcommerce.common.currency.dao.BroadleafCurrencyDaoImpl$$FastClassBySpringCGLIB$$a820f414.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:738) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:673) at org.broadleafcommerce.common.currency.dao.BroadleafCurrencyDaoImpl$$EnhancerBySpringCGLIB$$6c4cbe9c.findDefaultBroadleafCurrency(<generated>) at org.broadleafcommerce.common.currency.service.BroadleafCurrencyServiceImpl.findDefaultBroadleafCurrency(BroadleafCurrencyServiceImpl.java:47) at org.broadleafcommerce.common.currency.service.BroadleafCurrencyServiceImpl$$FastClassBySpringCGLIB$$6e082cf4.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:669) at org.broadleafcommerce.common.currency.service.BroadleafCurrencyServiceImpl$$EnhancerBySpringCGLIB$$f35d7848.findDefaultBroadleafCurrency(<generated>) at org.broadleafcommerce.common.web.BroadleafCurrencyResolverImpl.resolveCurrency(BroadleafCurrencyResolverImpl.java:98) at org.broadleafcommerce.common.web.BroadleafRequestProcessor.process(BroadleafRequestProcessor.java:138) at org.broadleafcommerce.common.web.BroadleafRequestFilter.doFilterInternalUnlessIgnored(BroadleafRequestFilter.java:109) at org.broadleafcommerce.common.web.filter.AbstractIgnorableOncePerRequestFilter.doFilterInternal(AbstractIgnorableOncePerRequestFilter.java:58) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:178) at org.broadleafcommerce.common.web.filter.IgnorableOpenEntityManagerInViewFilter.doFilterInternal(IgnorableOpenEntityManagerInViewFilter.java:54) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.broadleafcommerce.common.web.filter.SecurityBasedIgnoreFilter.doFilter(SecurityBasedIgnoreFilter.java:77) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) - locked <0x00000000f8699238> (a org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper) at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@17.0.9/ThreadPoolExecutor.java:1136) at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@17.0.9/ThreadPoolExecutor.java:635) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(java.base@17.0.9/Thread.java:840) 49 затем java -jar sjk.jar jcmd -s 127.0.0.1:5555 -c JFR.start settings=profile filename=dump1.jfr duration=30s Started recording 1. The result will be written to: /app/dump1.jfr мы смогли получить дамп потоков и запустить сессию JFR для процесса в контейнере.

    Инструменты, такие как jconsole или MissionControl так же смогут работать через прокси.

    50 Зарустите jconsole и попробуйте подключиться к процесу в контейнере используя адресс 127.0.0.1:5555.

    Завершение работы

    Завершим работу тестового стенда.

    Остановите JMX прокси процесс в консоле B.
    Удалите директорию LABDIR/blf-demo/pids (например rm -rf pids).
    Остановите jconsole.
    Проверьте выполняющиеся java процессы с помощью jcmd и остановие процессы демострационного стенда если они попрежнему выполняются.
    Удалите контейнер демонстрационного приложения docker rm -f storefront