2015-12-03 18 views
12

Ho diversi processi Java e sto cercando di gestire i dump dell'heap creati quando si verifica l'errore OOM. Quando dico gestisco intendoNome memoria file di heap automatico di memoria esaurita Java

  • nome mucchio discarica in modo diverso, in base al processo di origine
  • eliminare più vecchio mucchio discariche per risparmiare spazio su disco

Quando scaricate mucchio sul OOM con

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp 

la JVM crea un file con il seguente nome java_pidXXXX.hprof nella cartella/tmp specificata (dove XXXX è il PID del processo). È comunque necessario specificare un formato diverso in cui PID e DATE vengono utilizzati per creare il nome del file? Dopo aver cercato su google per un'ora ho provato myPrefix_ $, {pid}, 'data' .. ecc. Le uniche due cose che funzionano sono

    non
  1. specificare il nome del file e si ottiene java_pidXXXX.hprof
  2. specificare un nome di file statico per esempio \ Tmp \ OOM.hprof.

se la cartella \ tmp non esiste, non viene creata, né viene creato il dump dell'heap.

Quello idea che potrebbe usare è quello di aggiungere un comando in caso di errore OOM

-XX:OnOutOfMemoryError="doSomething.sh %p" 

ma io cercavo di evitarlo come ho bisogno di distribuire il "doSomething.sh"

+1

Perché hai bisogno della data nel nome? Se si desidera eliminare i file più vecchi, è possibile farlo con l'ora di modifica dei file, non è necessario la data nel nome. – RealSkeptic

risposta

4

La -XX:HeapDumpPath sulla riga di comando non ti dà più flessibilità rispetto a quello che avete già scoperto. Cioè, è possibile:

  • Impostare un nome di directory, quindi il nome predefinito java_pidXXX.hprof verrà creato in tale directory.
  • Impostare un nome file e tale file verrà utilizzato così com'è.

Il codice pertinente nella sorgente HotSpot è heapDumper.cpp. Leggendolo, non cerca alcuna "sequenza magica" all'interno del percorso specificato:

  • Controlla se il percorso specificato è una directory. In tal caso, lo utilizza come prefisso, aggiunge un separatore di file e utilizza il nome file predefinito che è costituito da parti codificate utilizzando un formato stringa che non è sotto il tuo controllo.
  • Se non è una directory, la utilizza solo così com'è.
  • Se non è il primo dump della vita di questa JVM, aggiunge anche un numero di sequenza.

Questo è tutto. Nessuna analisi del percorso oltre a determinare se si tratta di una directory o meno.

L'unica flessibilità che è possibile aggiungere è utilizzare le capacità della shell quando si costruisce il nome sulla riga di comando. Ecco perché potresti vedere alcuni esempi sul web che usano qualcosa come name_`date`.ext - questo viene elaborato dalla shell, che sostituisce `date` con la data corrente una volta. Cioè, il nome del file avrà sempre la data/ora in cui la shell ha elaborato il comando e avviato la JVM, non la data/ora in cui è stato creato il dump. Se è abbastanza buono per te, puoi usarlo. Si noti che al giorno d'oggi è considerato più accettabile utilizzare la sintassi name_$(date).ext.

Se è necessaria la data per poter rimuovere i vecchi file, è possibile rimuoverli in base all'ultima ora di modifica del file (l'utilità Unix/Linux find può esserti d'aiuto). Non è necessario avere la data nel nome.

Il trucco $(date) (o `date`) non aiuta con il PID. La shell può anche sostituire il PID corrente se si utilizza $$ - ma è il PID della shell che elabora la riga di comando, non la stessa procedura JVM. Tuttavia, se avvii la tua applicazione JAVA utilizzando il comando shell exec, essa riceve lo stesso ID di processo della shell da cui ha avuto origine, quindi puoi effettivamente utilizzare $$ per creare il tuo nome file. Ricorda però che nulla dopo lo exec verrà eseguito dal tuo script.

Quindi si può provare il cambiamento dinamico del nome del file che @apangin ha suggerito nella sua risposta. Si noti, tuttavia, che sarà probabilmente un po 'difficile individuare il tempo del dump stesso, poiché si vorrà avere il nome del file impostato prima che l'OOM avvenga effettivamente.

6

HeapDumpPath è un opzione VM gestibile. Ciò significa che puoi impostarlo su qualsiasi cosa desideri in runtime usando 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); 
Problemi correlati