sábado, 4 de diciembre de 2010

Volcado de memoria (hprof)

Debido a los errores de memoria cada vez más frecuentes (tipo java.lang.OutOfMemoryError: PermGen space failure) en las aplicaciones java que administramos en entornos de producción y a que en la mayoría de los casos se debe a un error de programación, java nos da la posibilidad de añadir una variable para realizar un volcado de la memoria.

Con esto obtenemos en un fichero una copia exacta del contenido de la memoria de la jvm en el momento del error. Este fichero nos servirá para tener una base sobre la cual estudiar el origen del problema (hay herramientas para procesar este tipo de ficheros, como jvisualvm).

Dicha variable sería:

-XX:HeapDumpPath=/ruta/donde/guardar/el/fichero/ -XX: +HeapDumpOnOutOfMemoryError


Sólo es factible sobre la versión de java 1.6 (por lo que no se podría aplicar a todas las aplicaciones).

Este fichero puede ser analizado con distintas herramientas: JVisualVM, Eclipse Memory Analyzer...

Si además quieres que ser avisado por correo cuando esto se produzca, se puede establecer en el cron (cada 5 min por ejemplo) que lance un script parecido al siguiente (este está hecho en python):

#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-

import os, string, datetime, time, smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.Utils import COMMASPACE, formatdate
from email import Encoders

#Variables
servidor_de_correo = "servidor de correo"
emisor= "maquina@dominio"

#Funcion para el envio de correo
def sendMail(to, subject, text, server=servidor_de_correo):
assert type(to)==list
fro = emisor

COMMASPACE = ', '
msg = MIMEMultipart()
msg['From'] = fro
msg['To'] = COMMASPACE.join(to)
msg['Date'] = formatdate(localtime=True)
msg['Subject'] = subject

msg.attach( MIMEText(text) )


smtp = smtplib.SMTP(server)
smtp.sendmail(fro, to, msg.as_string() )
smtp.close()


#Funcion de registro de log
def log (texto):
now = datetime.datetime.now()
f = open(fichero_log, 'a')
f.write(str (now.ctime()) + ' -> ' + texto + '\n')
f.close()

#Variables
cuenta_de_correo = "cuenta de correo donde mandar el aviso"
fichero_pid = "/var/run/tomcat5.pid"
f = open(fichero_pid,"r")
pid = str(f.read()).strip()
fichero_hprof = "java_pid" + pid + ".hprof"
fichero_log = "/ruta_fichero_log/comprueba.log"
existe = os.path.isfile("/tmp/" + fichero_hprof)
if existe:
log("Se ha creado el volcado de memoria.")
sendMail(
["cuenta_de_correo"],
"Volcado de memoria","Se ha producido un error de memoria provocando el volcado en el fichero " + fichero_hprof
)

else:
log("No se ha producido error de memoria ni volcado.")



El script simplemente estará revisando la existencia del fichero de volcado, que suele denominarse:

java_pid15546.hprof

donde 15546 es el pid del tomcat donde hemos configurado la variable para el hprof.

En cuanto detecte que existe, mandará un correo a la cuenta especificada.

No hay comentarios:

Publicar un comentario

Obtener informacion de repositorios a través de los metadatos .git publicados por error

 A raiz de CTF realizado recientemente, me ha parecido interesante publicar este post sobre los errores de seguridad que se encuentran en mu...