Ошибка памяти 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

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

class_loader    classes bytes   parent_loader   alive?  type

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

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

Ответ 1

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

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

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

Ответ 2

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

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