Ir al contenido principal

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.

Comentarios

Entradas populares de este blog

Conexión a bbdd oracle desde python

Para poder acceder a una bbdd oracle desde python tan sólo necesitaremos tener instalado: - cliente oracle (lo puedes obtener de la página de oracle y registrándote en la misma) - extensión cx_Oracle (lo puedes descargar desde la página http://cx-oracle.sourceforge.net/) La forma de utilizarlo lo podemos ver en el siguiente ejemplo: Con este script se pretende actualizar el campo de una tabla pasándole tres argumentos, dos para filtrar el dato y uno que será el nuevo valor. También hacemos uso de optparse para pasear los argumentos. #!/usr/bin/python # -*- coding: iso-8859-15 -*- import cx_Oracle, sys, os, datetime from optparse import OptionParser conn_str='usuario/pass@host:port/bbdd' log = '/ruta/para/log/script.log' #Fucion para escribir log def log (texto):         now = datetime.datetime.now()         f = open(log_propio, 'a')         f.write(str (now.ctime()) + ' -> ' + texto + '\n')         f.close() #Se parsea

Curso Django Segunda Parte

Continuamos con la segunda parte del mini curso de django. Respecto a la primera parte, he añadido una par de cosas: - La instalación de un paquete más: python-pygraphviz - Y la aplicación de un parche para django-smart-selects: https://github.com/GrAndSE/django-smart-selects/commit/7e2a8d572b3615cc39a3c9f9d60e1b60de06f46f Pues bien, ya tenemos creado un proyecto llamado misitio. Ahora es el momento de crear nuestra aplicación, la cual llamaremos inventario. Para crear un aplicación, simplemente hacemos: cd /opt/djcode/misitio python manage.py startapp inventario Tras la ejecución de este comando (que no devuelve nada por pantalla), tendremos un nuevo directorio bajo el proyecto misitio: ls -l inventario/ -rw-r--r-- 1 root root   0 mar 11 12:27 __init__.py -rw-r--r-- 1 root root  57 mar 11 12:27 models.py -rw-r--r-- 1 root root 383 mar 11 12:27 tests.py -rw-r--r-- 1 root root  26 mar 11 12:27 views.py De los ficheros que nos podemos encontrar, tenemos:

Configurar Nano Wifi TL-WN725N en Raspberry pi

Hace poco me regalaron una raspberry pi, y junto con ella, un dongle wifi usb TP-LINK, modelo TL-WN725N. En principio se supone que no debe haber problemas de compatibilidad entre este dongle wifi y nuestra raspberry, pero si la versión de nuestro dongle wifi es la 2 (en la caja viene como Ver:2.0) la cosa cambia. En mi caso tenía instada la última versión de raspbian, la cual traía una versión de kernel superior a la 3.10.18. Esta versión de kernel es la que funciona con nuestra modelo de dongle wifi (al menos según he podido averiguar). De modo que para poder reconocer el dongle wifi, tendremos que bajar a esta versión del kernel: sudo rpi-update 8fd111f77895450323abc5b34efde19548ffc480 Tras reiniciar, tendremos el siguiente kernel: Linux raspberrypi 3.10.18+ #587 Ahora sólo nos queda instalar el driver: wget https://dl.dropboxusercontent.com/u/80256631/8188eu-20131110.tar.gz tar -zxvf 8188eu-20131110.tar.gz                                          cat README