Утечка памяти в Java - jmap не показывает классы, а jstat

Я устраняю причину странной утечки памяти. Это специфично для Java8, не происходит на 7u79.

У меня нет доступа к коду Java. Я точно знаю, какое действие пользователя вызывает утечку, я знаю, что утечка связана с классами (а не с кучей), и нарушающие классы легко обнаружить с помощью +TraceClassLoading +TraceClassUnloading:

[Loaded com.mastercard.mcwallet.sdk.xml.allservices.ShoppingCartRequest$JaxbAccessorF_oAuthToken from __JVM_DefineClass__]
[Loaded com.mastercard.mcwallet.sdk.... thousand similar classes per one user action... ]

Эти классы, кажется, увеличивают выход счетчика классов на jstat -class:

Loaded  Bytes  Unloaded  Bytes     Time
 14045 26138.8        0     0.0     110.00   << buggy user action
 14675 26754.6        0     0.0     110.05
 15300 27364.9        0     0.0     110.10
 15304 27370.9        0     0.0     110.11
 15304 27370.9        0     0.0     110.11
 15304 27370.9        0     0.0     110.11
 15306 27374.0        0     0.0     110.11
 15306 27374.0        0     0.0     110.11
 15306 27374.0        0     0.0     110.11
 15306 27374.0        0     0.0     110.11   << buggy user action
 15930 27982.2        0     0.0     110.18
 16553 28589.3        0     0.0     110.23
 16553 28589.3        0     0.0     110.23

Дело в том, что эти классы никогда не собираются мусором из метапространства, никогда [Unloaded] и они не показывают в jmap -clstats, Команда сообщает о меньшем количестве классов, число не увеличивается, нет подозрительных загрузчиков классов:

class_loader    classes bytes   parent_loader   alive?  type

<bootstrap>     2574    4493256   null          live    <internal>
0x0000000087d016d0      1       1471    0x000000008237f088      dead    sun/reflect/DelegatingClassLoader@0x00007ff4135d02d0
... some lines omitted ...
0x000000008237f088      6505    12228227        0x0000000080383938      dead    org/apache/catalina/loader/WebappClassLoader@0x00007ff411546ad0
... some lines omitted ...
total = 600     14002   25351427            N/A         alive=1, dead=599           N/A

Звонит ли это по телефону или приносит какие-то советы, которые я мог бы передать программистам? Они говорят, что не могут обнаружить утечку. Могу ли я остановить эту утечку, просто поиграв с опциями JVM?

2 ответа

Решение

Я предполагаю, что JaxB загружает классы в вашу память, которые не являются сборщиком мусора. Metaspace не опустошится, если классы не выгружены.

Проверьте наличие проблемы с памятью JaxB для Java 8. Я думаю, что вы можете избавиться от этого исключения, меняя версию API зависимостей или переключая дополнительный параметр:

-Dcom.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize=true

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

Вы можете попробовать использовать Eclipse Memory Analyzer ( MAT) для проверки вашего дампа кучи, и он может показывать проблемные области, классы и экземпляры, которые имеют ссылки на ошибочные классы.

Другие вопросы по тегам