jps не перечисляет процесс tomcat, и jmap не удается создать дамп кучи

#java #heap-dump #jmap #eclipse-memory-analyzer #openj9

#java #куча-дамп #jmap #eclipse-memory-analyzer #openj9

Вопрос:

У меня запущен сервер tomcat (9.0.39.0), запущенный пользователем cpappt и работающий с pid: 1682650. Машина, на которой работает этот сервер, — это не голый металл, а VMware машина, и JVM ис из OpenJ9

 > ps -ef | grep Bootstrap
cpappt   1682650       1  0 Jan01 ?        01:09:58 /srv/jdk11/bin/java
  -Djava.util.logging.config.file=/srv/test/cpappt/tomcat/conf/logging.properties
  -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -server 
  -Xms32m -Xmx2048m -XX: HeapDumpOnOutOfMemoryError
  -Dcrewportalenvironment=test
  -Denvironment=test
  -Doracle.net.tns_admin=/CONFIG/global/ORA/HA
  -Dspring.profiles.active=test,notification-services-intern
  -Djdk.tls.ephemeralDHKeySize=2048
  -Djava.protocol.handler.pkgs=org.apache.catalina.webresources
  -Dorg.apache.catalina.security.SecurityListener.UMASK=0022
  -Djava.awt.headless=true
  -Dcom.sun.management.jmxremote
  -Dfile.encoding=UTF-8
  -Dsun.jnu.encoding=UTF-8
  -Dcom.sun.management.jmxremote.port=7305
  -Dcom.sun.management.jmxremote.ssl=false
  -Dcom.sun.management.jmxremote.password.file=conf/jmxremote.password
  -Dignore.endorsed.dirs= -classpath /srv/test/cpappt/tomcat/bin/bootstrap.jar:/srv/test/cpappt/tomcat/bin/tomcat-juli.jar
  -Dcatalina.base=/srv/test/cpappt/tomcat
  -Dcatalina.home=/srv/test/cpappt/tomcat
  -Djava.io.tmpdir=/srv/test/cpappt/tomcat/temp org.apache.catalina.startup.Bootstrap start
 

Я хочу извлечь heap dump файл tomcat для анализа потенциальной утечки памяти.

Я пытался использовать jps для получения сервера pid tomcat, к сожалению, я вижу только самого pid jps себя.

 > jps -l
952152 jdk.jcmd/openj9.tools.attach.diagnostics.tools.Jps
 

и я также запускаю jps команду от имени того же пользователя, который запустил сервер tomcat

 > whoami 
cpappt
 

Я также попытался запустить jps команду, добавив java.io.tmpdir указанную в сценарии запуска tomcat, что приводит к тому же результату, что и раньше (примечание: tmpdir само по себе пустое).

 jps -l -J-Djava.io.tmpdir=/srv/test/cpappt/tomcat/temp
 

(Дополнительное замечание: если я запустил небольшую «Foo-программу», jps она показывает мне pid эту программу.)

Затем я попытался создать дамп кучи, используя команду pid from ps , которая не удалась:

 > jmap -dump:live,format=b,file=/tmp/dump.hprof 1682650
unrecognized option -dump:live,format=b,file=/tmp/dump.hprof
jmap: obtain heap information about a Java process
 Usage:
    jmap <option>* <vmid>
        <vmid>: Attach API VM ID as shown in jps or other Attach API-based tools
        <vmid>s are read from stdin if none are supplied as arguments
    -histo: print statistics about classes on the heap, including number of objects and aggregate size
    -histo:live : Print only live objects
    -J: supply arguments to the Java VM running jmap
NOTE: this utility might significantly affect the performance of the target VM.
At least one option must be selected.
 

Если я просто попытаюсь просмотреть гистограмму, это также не удастся:

 > jmap -histo:live 1682650
Error getting data from 1682650: Exception connecting to 1682650
 

Также jcmd не может создать дамп:

 > jcmd 1682650 GC.heap_dump /tmp/heapdump
Error getting data from 1682650: Exception connecting to 1682650
...
 

Я почему-то подозреваю, что обе проблемы ( jps и jmap ) связаны…
Итак, если у кого-нибудь есть идея, в чем может быть проблема или даже как я мог бы создать дамп кучи, это было бы здорово.

Дополнительная информация с сервера tomcat (и java):

 Server version number: 9.0.39.0
OS Name:               Linux
OS Version:            5.7.0-0.bpo.2-amd64
Architektur:           amd64
Java Home:             /srv/jdk-11.0.8 10_openj9
JVM Version:           11.0.8 10
JVM Hersteller:        Eclipse OpenJ9

> java -version
openjdk version "11.0.8" 2020-07-14
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.8 10)
Eclipse OpenJ9 VM AdoptOpenJDK (build openj9-0.21.0, JRE 11 Linux amd64-64-Bit Compressed References 20200715_697 (JIT enabled, AOT enabled)
OpenJ9   - 34cf4c075
OMR      - 113e54219
JCL      - 95bb504fbb based on jdk-11.0.8 10)

> which java
/srv/jdk11/bin/java

> which jps
/srv/jdk11/bin/java

> which jmap 
/srv/jdk11/bin/jmap
 

Обновление: 2021-01-09

Я, наконец, смог связаться с коллегой, который знает пароль для пользователя jmx, поэтому с помощью jconsole I удалось вызвать a heap dump , но я мог только позвонить triggerClassicHeapDump() . Я скопировал файл на свой локальный компьютер и хотел проанализировать его с Eclipse MemoryAnalyzer помощью (я также добавил Diagnostic Tool Framework for Java (DTFJ) ).

Но когда я пытаюсь открыть файл, я теперь получаю сообщение об ошибке…

 Error opening heap dump 'heapdump.20210119.100934.2621412.0001.txt'. Check the error log for further details.
Error opening heap dump 'heapdump.20210119.100934.2621412.0001.txt'. Check the error log for further details.
Error opening heap dump 'heapdump.20210119.100934.2621412.0001.txt'
Unable to read dump .../heapdump.20210119.100934.2621412.0001.phd metafile .../heapdump.20210119.100934.2621412.0001.txt in DTFJ format DTFJ-PHD (java.io.IOException)
Unable to read dump .../heapdump.20210119.100934.2621412.0001.phd metafile .../heapdump.20210119.100934.2621412.0001.txt in DTFJ format DTFJ-PHD
Error parsing Javacore (java.io.IOException)
Error parsing Javacore
com.ibm.dtfj.javacore.parser.framework.scanner.ScannerException: Maximum line length (32768) exceeded. Input file corrupt or not a javacore. (com.ibm.dtfj.javacore.parser.framework.parser.ParserException)
com.ibm.dtfj.javacore.parser.framework.scanner.ScannerException: Maximum line length (32768) exceeded. Input file corrupt or not a javacore.
Maximum line length (32768) exceeded. Input file corrupt or not a javacore. (com.ibm.dtfj.javacore.parser.framework.scanner.ScannerException)
Maximum line length (32768) exceeded. Input file corrupt or not a javacore.
Unable to read dump .../heapdump.20210119.100934.2621412.0001.txt metafile null in DTFJ format DTFJ-Javacore (java.io.IOException)
Unable to read dump .../heapdump.20210119.100934.2621412.0001.txt metafile null in DTFJ format DTFJ-Javacore
Error parsing Javacore (java.io.IOException)
Error parsing Javacore
com.ibm.dtfj.javacore.parser.framework.scanner.ScannerException: Maximum line length (32768) exceeded. Input file corrupt or not a javacore. (com.ibm.dtfj.javacore.parser.framework.parser.ParserException)
com.ibm.dtfj.javacore.parser.framework.scanner.ScannerException: Maximum line length (32768) exceeded. Input file corrupt or not a javacore.
Maximum line length (32768) exceeded. Input file corrupt or not a javacore. (com.ibm.dtfj.javacore.parser.framework.scanner.ScannerException)
Maximum line length (32768) exceeded. Input file corrupt or not a javacore.
 

Ответ №1:

Я добавил -Xdump:heap:events=user (см. Xdump Option Builder) в сценарий запуска tomcat и перезапустил сервер.

 > ps -ef | grep Bootstrap
cpappt   1919301       1 99 14:38 pts/0    00:01:00 /srv/jdk11/bin/java 
 -Xms32m -Xmx2048m -XX: HeapDumpOnOutOfMemoryError
 -Xdump:heap:events=user
 ...
 

Теперь я могу создать дамп кучи, используя kill -3 <pid> (посмотрите на суперпользователя: что означает kill-3).
В каталоге были созданы два файла catalina.base :

  • javacore.<XXX>.txt (исходный дамп потока (-3 := SIGQUIT )) и
  • heapdump.<YYY>.phd (ну, фактический дамп кучи)

Наконец я смог открыть heapdump.<YYY>.phd файл с помощью Eclipse MAT

Дополнительное замечание: мы обновили openj9 версию до текущей версии (23.0).

 > java -version 
openjdk version "11.0.9" 2020-10-20
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.9 11)
Eclipse OpenJ9 VM AdoptOpenJDK (build openj9-0.23.0, JRE 11 Linux amd64-64-Bit Compressed References 20201022_810 (JIT enabled, AOT enabled)
 

Теперь jps также находит сервер tomcat

 > jps -l
1919301 org.apache.catalina.startup.Bootstrap
1921897 jdk.jcmd/openj9.tools.attach.diagnostics.tools.Jps
 

Также jcmd работает:

 > jcmd 1919301 Dump.heap dump
Dump written to .../tomcat/dump
 

Ответ №2:

Также рассмотрите возможность использования -Xdump:system:events=user, поскольку сгенерированный основной файл содержит намного больше информации, однако существуют проблемы с чтением IBM DTFJ основных файлов, сгенерированных OpenJ9.

Анализатор памяти также может генерировать дампы кучи — см. Файл> Получить дамп кучи, но «Прикрепить API» и «Прикрепить API с помощью вспомогательной JVM» может потребовать некоторой настройки. Анализатор памяти 1.12 имеет некоторые улучшения в получении дампов кучи, поэтому попробуйте последнюю версию.