2015-08-20 2 views
2

Je suis à la recherche dans le débogage d'une erreur "OutOfMemoryError: Metaspace" dans mon application. Juste avant le oome que je vois ce qui suit dans les journaux gc:Comment mesurer la fragmentation dans le métaspace de Hotspot?

{Heap before GC invocations=6104 (full 39): 
par new generation total 943744K, used 0K [...) 
    eden space 838912K, 0% used [...) 
    from space 104832K, 0% used [...) 
    to space 104832K, 0% used [...) 
concurrent mark-sweep generation total 2097152K, used 624109K [...) 
Metaspace  used 352638K, capacity 487488K, committed 786432K, reserved 1775616K 
    class space used 36291K, capacity 40194K, committed 59988K, reserved 1048576K 
2015-08-11T20:34:13.303+0000: 105892.129: [Full GC (Last ditch collection) 105892.129: [CMS: 624109K->623387K(2097152K), 3.4208207 secs] 624109K->623387K(3040896K), [Metaspace: 352638K->352638K(1775616K)], 3.4215100 secs] [Times: user=3.42 sys=0.00, real=3.42 secs] 
Heap after GC invocations=6105 (full 40): 
par new generation total 943744K, used 0K [...) 
    eden space 838912K, 0% used [...) 
    from space 104832K, 0% used [...) 
    to space 104832K, 0% used [...) 
concurrent mark-sweep generation total 2097152K, used 623387K [...) 
Metaspace  used 352638K, capacity 487488K, committed 786432K, reserved 1775616K 
    class space used 36291K, capacity 40194K, committed 59988K, reserved 1048576K 
} 

D'après ce que je peux voir, la capacité Metaspace est même pas en voie de la taille engagée (dans ce cas, -XX:MaxMetaspaceSize=768m). Je suspecte donc la fragmentation de Metaspace, ce qui empêche l'allocateur de trouver un nouveau segment pour le nouveau classloader.

Je connais -XX:PrintFLSStatistics mais cela ne concerne que le CMS, pas la mémoire native. Donc, ma question est la suivante: y a-t-il une aide au débogage similaire à PrintFLSStatistics disponible pour la mémoire native de Hotspot?

Utilise la machine virtuelle serveur Java HotSpot (TM) 64 bits (25.45-b02) pour linux-amd64 JRE (1.8.0_45-b14).

Répondre

3

Je viens de me pencher sur l'implémentation du Métaspace dans HotSpot. Le Metaspace est divisé en blocs et géré à l'aide d'une liste de diffusion. La fragmentation est donc une raison possible de votre problème.

J'ai également regardé les drapeaux de la machine virtuelle HotSpot (-XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal), il n'y a pas d'indicateur dans la version finale.

Toutefois, il existe une méthode dump() dans la classe Metaspace qui semble être déclenchée en définissant l'indicateur -XX:+TraceMetadataChunkAllocation. Il y a aussi le -XX:+TraceMetavirtualspaceAllocation qui semble être intéressant pour vous. Cependant, ce sont des drapeaux "develop", ce qui signifie que vous avez besoin d'une version de débogage de la machine virtuelle.

+1

Belle trouvaille, je suis en train de construire une version de débogage et de les essayer. – mabi

1

@ réponse de loonytune fonctionne très bien, mais je veux donner un peu plus en détail:

Pour le contexte, « Le Metaspace » est une collection de metaspaces, un par chargeur de classe. Chaque métaspace contient une liste d'objets VirtualSpace sur lesquels Metachunk de tailles différentes sont allouées. Ces segments contiennent MetaBlock s, qui sont les vrais conteneurs pour les métadonnées.

je besoin d'un JRE de débogage pour exécuter ces drapeaux, donc suivant this tuorial J'ai vérifié le dépôt OpenJDK (je renomme la caisse à vm parce que les scripts de compilation semblent en désaccord avec le nom du dossier jdk8), couru

~/vm$ bash configure --enable-debug 
~/vm$ DISABLE_HOTSPOT_OS_VERSION_CHECK=ok make all 

et utilisé vm/build/linux-x86_64-normal-server-fastdebug/images/j2re-image en tant que mon exécution Java.

Les lignes de journaux générés ressembler à ceci:

VirtualSpaceNode::take_from_committed() not available 8192 words space @ 0x00007fee4cdb9350 128K, 94% used [0x00007fedf5e22000, 0x00007fedf5f13000, 0x00007fedf5f22000, 0x00007fedf6022000)

qui indique que le VirtualSpace actuel est plein et ne peut pas tenir un autre morceau de la taille 8192 word demandée. Cela entraînera ce méta-espace pour passer à un autre VirtualSpace.

ChunkManager::chunk_freelist_allocate: 0x00007fee4c0c39f8 chunk 0x00007fee15397400 size 128 count 0 Free chunk total 7680 count 15

ChunkManager::chunk_freelist_allocate: 0x00007fee4c0c39f8 chunk 0x00007fedf6021000 size 512 count 14 Free chunk total 7168 count 14

Cela se produit lorsqu'un nouveau Metachunk est affecté, dans le premier cas, il est de 128 mots grand et utilise la liste des petits morceaux. Comme vous pouvez le voir, la prochaine demande va aux morceaux de taille moyenne (de taille 512) et laisse 14 morceaux au total. Une fois que le total libre atteint 0, un GC complet est nécessaire pour augmenter la taille totale du méta-espace.

Notez que si vous spécifiez -verbose, vous obtenez encore plus de résultats des deux indicateurs ci-dessus.