J'ai plusieurs processus Java et j'essaie de gérer les vidages de tas créés en cas d'erreur OOM. Quand je dis gérer, je veux dire
Lors du dumping de tas sur MOO avec
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp
la JVM crée un fichier avec le nom suivant Java_pidXXXX.hprof dans le dossier/tmp spécifié (où XXXX est le PID du processus). Est-il possible de spécifier un format différent où le PID et la DATE sont utilisés pour créer le nom de fichier? Après avoir googlé pendant une heure, j'ai essayé myPrefix_ $, {pid}, 'date' .. etc. Les deux seules choses qui fonctionnent sont
si le dossier\tmp n'existe pas, il n'est pas créé, ni le vidage de tas n'est créé.
La seule idée qui pourrait être utilisée est d'ajouter une commande sur l'erreur OOM
-XX:OnOutOfMemoryError="doSomething.sh %p"
mais j'essayais de l'éviter car je dois déployer le "doSomething.sh"
Le -XX:HeapDumpPath
Sur la ligne de commande ne vous donne pas plus de flexibilité que ce que vous avez déjà découvert. Autrement dit, vous pouvez soit:
Java_pidXXX.hprof
Sera créé dans ce répertoire.Le code pertinent dans la source HotSpot est heapDumper.cpp . En le lisant, il ne recherche aucune "séquence magique" à l'intérieur du chemin donné:
C'est ça. Pas d'analyse du chemin au-delà de déterminer s'il s'agit d'un répertoire ou non.
La seule flexibilité que vous pouvez y ajouter est d'utiliser les capacités du shell lorsque vous construisez le nom sur la ligne de commande. C'est pourquoi vous pouvez voir quelques exemples sur le Web qui utilisent quelque chose comme name_`date`.ext
- cela est traité par le Shell, qui remplace `date`
Par la date actuelle une fois . C'est-à-dire que le nom de fichier aura toujours la date/heure à laquelle le shell a traité la commande et démarré la JVM - pas la date/heure à laquelle le vidage a été créé. Si cela vous convient, vous pouvez l'utiliser. Notez que de nos jours, il est considéré comme plus acceptable d'utiliser la syntaxe name_$(date).ext
.
Si vous avez seulement besoin de la date pour pouvoir supprimer les anciens fichiers, vous pouvez les supprimer en fonction de la dernière heure de modification du fichier (l'utilitaire Unix/Linux find
peut vous aider avec cela). Il n'est pas nécessaire d'avoir la date dans le nom.
L'astuce $(date)
(ou `date`
) Ne vous aide pas avec le PID. Le Shell peut également remplacer le PID actuel si vous utilisez $$
- mais c'est le PID du Shell qui traite la ligne de commande, pas le processus JVM lui-même. Cependant, si vous démarrez votre application Java à l'aide de la commande Shell exec
, elle reçoit le même ID de processus que le shell d'où elle provient, vous pouvez donc réellement utiliser $$
pour construire votre nom de fichier. N'oubliez pas que rien après exec
ne sera exécuté à partir de votre script.
Vous pouvez donc essayer le changement dynamique du nom de fichier suggéré par @apangin dans sa réponse. Notez, cependant, qu'il sera probablement un peu difficile de déterminer l'heure du vidage lui-même, car vous souhaiterez que le nom de fichier soit défini avant que le MOO ne se produise réellement.
HeapDumpPath
est une option gérable VM. Cela signifie que vous pouvez la définir comme vous le souhaitez lors de l'exécution à l'aide de JMX.
String pid = ManagementFactory.getRuntimeMXBean().getName();
pid = pid.substring(0, pid.indexOf('@'));
String date = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
String fileName = "/tmp/heap_" + pid + "_" + date + ".dump";
HotSpotDiagnosticMXBean bean = ManagementFactory.newPlatformMXBeanProxy(
ManagementFactory.getPlatformMBeanServer(),
"com.Sun.management:type=HotSpotDiagnostic",
HotSpotDiagnosticMXBean.class);
bean.setVMOption("HeapDumpOnOutOfMemoryError", "true");
bean.setVMOption("HeapDumpPath", fileName);