12
votes

Quand un JVM se bloque (Segfault) pendant la collecte des ordures, comment puis-je découvrir ce qui était collecté?

Je reçois des segfault dans mon jvm à grossièrement la même phase de l'application, mais avec des traces de pile variable dans le rapport d'accident. Il semble toujours se produire pendant la GC, cependant.

Étant donné que l'accident se produit dans les trois JVM que j'ai essayé (OpenJDK 6, Oracle 1.6.0_25 et 1.7.0) et avec deux GCS chacun (collecteur parallèle et CMS), et cela arrive autour de la même zone de l'application, je Figuré, si je pouvais trouver ce que le GC essayait de collecter, je pourrais repérer une certaine particularité dans mon code qui provoque cette crash.

  • Y a-t-il des pratiques de codage bien connues pour être problématiques pour GC?
  • Quelles méthodes sont disponibles pour diagnostiquer ce problème?
  • Puis-je faire des suppositions éduquées sur l'endroit où dans ma demande, ce problème est déclenché?
  • Quels paramètres (GC Tuning) Puis-je jouer avec pour réduire le problème?
  • Y a-t-il un moyen de repérer (éventuellement) des données problématiques dans un dépotoir de tas?

6 commentaires

Ajout de la balise JNI car c'est clairement un bug dans une bibliothèque de JNI alors que Peter Lawrey a déjà souligné.


Je serais très intéressé à voir ce qui causait l'accident.


J'ai réussi à planter le Sun Jvm sans Jni.


C'est Eclipselink, de toute façon. Je sais juste. Ça doit aller. Il l'a eu depuis longtemps. Je vais me sortir moi-même.


@Casey sûr que vous pouvez, mais quelle est la probabilité un bogue dans la mise en œuvre de la JVM, comparé à une fonction de corruption de la JNI?


Cela pourrait aider à stackoverflow .com / questions / 5395337 / ...


4 Réponses :


1
votes
  • Les défauts SEG ont des codes d'erreur spécifiques au début du décharge http://fr.wikipedia.org/wiki/segmente_fault

  • Vous pouvez utiliser thread.dumpstacktrace pour voir ce qui se passe dans cette application Si vous savez exactement où votre application est gelée ou allez geler après une certaine action ou événement, vous pouvez Ctrl + Break Windows ou Ctrl + \ pour obtenir une décharge de thread et voir ce qui se passe.

  • au lieu de deviner vaguement, vous pouvez commenter certaines sections du code pour savoir quelle boucle ou objet ou tampon prennent trop de temps

  • Selon votre situation, vous pouvez envisager des outils spécifiques.


0 commentaires

8
votes

Cela se produira si vous avez une bibliothèque JNI qui gère la mémoire incorrecte. Le problème ne montre pas immédiatement. Cependant, lorsqu'un GC est effectué, il étudie toute la mémoire, voyages sur la référence corrompue et tue la JVM. c'est-à-dire que la corruption aurait pu se produire à tout moment depuis le dernier GC complet.


8 commentaires

Cela semble difficile à déboguer. Tout ce que je peux faire du tout?


Donc, même si le problème semble se produire pendant GC, cela ne la limite pas à un bug dans un finisseur?


@Hannofiniez Eh bien il y a Valgrind and CO, mais le problème est que le code hotspot lui-même est .. bien cela brise la plupart (je dirais tout, mais qui sait) de ces outils. Aucune idée si vous pouvez obtenir Valgrind pour vérifier votre propre code.


@Aedwald Vous ne pouvez pas produire de Segfault en code PURE Java sans bug dans le JVM sous-jacent (ce qui est possible, mais peu probable). Le GC doit regarder (et traverser) tous les pointeurs, donc si vous écrivez des ordures dans l'une de celles-ci, c'est tout ce qu'il y en a.


Existe-t-il une façon de reconnaître les données problématiques dans un dépotoir de tas? Je serais probablement en mesure d'en faire un qui est susceptible de le contenir.


"Vous ne pouvez pas produire de Segfault dans le code Java pur" Je sais. J'aurais dû dire "un bogue dans un finaliseur qui appelle le code JNI".


@Readwald Bien OK, oui, nous ne pouvons pas le réduire. Tout ce que nous savons: Certains code JNI ont été appelés que cela a corrompu le tas, où cela est arrivé est immatériel (et ne peut être garanti - pourrait être un finisseur, pourrait être autre chose). En fait, les finaliseurs ne sont même pas exécutés pendant que GC: ils sont exécutés dans un fil séparé en même temps que le reste du programme.


@Voo, vous pouvez obtenir une faute SEG en utilisant Sun.Misc.unsafe. Vous pouvez également corrompre la mémoire afin qu'elle échoue sur le prochain GC. Je ne sais pas comment vous pouvez corrompre la mémoire de manière à ce que le GC ne se plante pas, mais le finaliseur le fait. Si vous avez corrompu la référence, le finaliseur utilise peut-être le faire.



0
votes
  • Je vous suggère que vous obteniez à la fois des vidages de thread et du dépotoir, vous pouvez le faire à partir de la ligne de commande utilise un outil tel que visuel VM
  • Je pense que la vidange de tas d'instantané de la mémoire JVM fournira des informations sur les objets vivants et leurs allocations. Si vous analysez le tas à l'aide de Visual VM, il fournit un rapport détaillé sur tous les objets sur le tas
  • Je vous suggérerais de bosse de la collection GC sur votre application à Verbose et d'analyser à l'aide d'un outil tel que tagtraum
  • Si vous pouvez joindre un profileur JVM qui peut fournir beaucoup d'informations ou Si vous avez une idée générale du flux de travail qui cause le problème, vient de profiler en isolant

0 commentaires

0
votes

Nous étions également confrontés à une question similiaire. Il n'y avait pas de motif que nous pouvions voir et il était assez aléatoire mais qui se passe soit sur GC ou GC complet. Pour nous, il s'est avéré être un problème avec les modules RAM. Nous l'avons identifié à l'aide de MEMTEST86 + sur le serveur Ubuntu.


0 commentaires