Archivo de la categoría: Java

Solucionar el error: ‘MAX_FRAMES_PER_TRACE limit’

Trabajando con Spring Roo y STS, es posible que llegado el momento os encontréis de bruces con este error:

28-feb-2012 10:08:12 com.springsource.insight.intercept.trace.SimpleFra meBuilder enter
GRAVE: Frame stack exceeded MAX_FRAMES_PER_TRACE limit or has been aborted limit: 3000 frameCount: 3000 aborted: false
28-feb-2012 10:08:12 com.springsource.insight.intercept.trace.SimpleFra meBuilder enter
GRAVE: Frame stack exceeded MAX_FRAMES_PER_TRACE limit or has been aborted limit: 3000 frameCount: 1 aborted: true
28-feb-2012 10:08:12 com.springsource.insight.intercept.trace.SimpleFra meBuilder enter
GRAVE: Frame stack exceeded MAX_FRAMES_PER_TRACE limit or has been aborted limit: 3000 frameCount: 1 aborted: true
28-feb-2012 10:08:12 com.vaadin.Application terminalError
GRAVE: Terminal error:
java.lang.IllegalStateException: Imbalanced frame stack! (exit() called too many times)

Este error surge por las limitaciones de Spring Insight, la máquina virtual con el servidor de desarrollo integrado en STS, que con la configuración por defecto nos genera este error en cuanto empecemos a desarrollar una aplicación que realice muchas operaciones sobre una base de datos.

Para solucionarlo, tan sencillo como añadir en la configuración de ejecución «Run -> Run Configurations -> VMware vFabric tc Server Developer Edition v2.6» el siguiente argumento al arranque de la máquina: «-Dinsight-max-frames=200000»

Tras añadir la opción, paramos el servidor y al volverlo a iniciar y lanzar nuestro proceso, ya no debería darnos el error. En el caso del ejemplo, con el valor incrementado a 200.000 nuestro proceso no volvió a fallar en local.

Java: Crear un ejecutable para tu aplicación.

En ocasiones, aunque JAVA tenga carácter multiplataforma es posible que necesitemos crear un Ejecutable para Windows, un .exe, para nuestra aplicación JAVA.

Sea por exigencia de nuestro cliente, o por el mero hecho de querer hacer una distribución estándar para un entorno Windows.

El programa que vamos a utilizar se llama JSmooth, y es un programa gratuito que teneis disponible en Sourceforge.net, y en su página teneis disponibles manuales en HTML y PDF,.

En primer lugar, debemos de descargarnos el programa e instalarlo en nuestra máquina. Tras ello lo ejecutamos y llegamos a la primera página:

Skeleton.

Pincharemos sobre los iconos de la izquierda para ir a ‘Skeleton‘, donde debemos de indicar para qué tipo de aplicación queremos crear un ejecutable, teniendo para ello un desplegable con varias opciones. Cada opción, una vez seleccionada, cuenta con una descripción del tipo de aplicación.
En nuestro caso, seleccionamos el tipo ‘Windowed Wrapper‘ que es el que más se ajusta a la aplicación Swing que tenemos.

En la parte inferior de la pantalla, vemos algunas opciones. La primera de ellas es el mensaje que queremos que se muestre cuando no se pueda encontrar un JDK instalado en la máquina cliente. Asociada a esta primera, la opción url nos permite indicar a qué url llevar al usuario si selecciona descargar un JDK.
Por defecto la url es la que SUN tiene para JAVA con la descarga directa del último JDK o JRE.

La siguente opción es si queremos que el proceso JAVA, que se lanzará para nuestra aplicación, se ejecute dentro del proceso .exe o como un proceso aparte. En nuestro caso seleccionamos que lo lance dentro del .exe.

A continuación, tenemos la opción ‘Single Instance‘, que nos servirá para indicar si queremos o no que solo se permita una instancia de nuestra aplicación ejecutándose a la vez. La marcamos porque nos interesa que solo se permita una instancia.

Las dos siguientes son propias del JSmooth, y en nuestro caso no nos interesan.

Executable.

Pasamos al siguiente paso pulsando sobre ‘Executable‘.

Aquí, le indicamos el nombre del .exe (y en qué directorio nos lo generará) que querremos que tenga nuestra aplicación.
Le podremos asociar un icono al ejecutable, y decirle cuál será el directorio de trabajo de la aplicación una vez lanzada. Le asociamos un icono, y dejamos el campo en blanco para no obligar a nuestra aplicación a tener un directorio de trabajo pre-fijado.

Application.

Pasamos al siguente paso pulsando sobre el icono ‘Application‘, y en la siguiente pantalla pasamos a configurar la clase principal de nuestra aplicación y los distintos argumentos que podemos pasarle a la misma, o a la Máquina Virtual de JAVA.

Para seleccionar la ‘Main Class‘, primero cargaremos en la sección Classpath el fichero .jar que contiene nuestra aplicación, y luego pulsaremos sobre el botón a la derecha del campo […] para seleccionar entre todas las clases del JAR la que nos interesa.

Si no tenemos argumentos que pasar a nuestra aplicación, dejamos el siguiente campo en blanco.

También podemos elegir que se incluya un JAR dentro del .exe, que será extraido al directorio de trabajo cuando lancemos la aplicación.

Y en Classpath incluiremos todos los .jar que necesite nuestra aplicación (en la siguiente entrega veremos cómo distribuirlos con el instalador).

JVM Selection.

Pasamos a la siguiente sección, y aquí podemos indicar cuál es la versión mínima, y máxima, con la que se puede ejecutar nuestra aplicación. En nuestro caso, he puesto como mínima la 1.5, y como máxima la 1.6.

Podemos indicar, si así lo queremos, que se use un JRE (Java Runtime Environment) que se distribuya con nuestra aplicación.
Aquí, lo que he hecho ha sido copiar el directorio jre del JDK que estoy usando al directorio donde voy a tener el .exe, y referenciarlo con ‘./jre’, para que lo busque más adelante en el directorio de trabajo.

La siguiente opción sirve para ordenar cómo se buscará un JRE en el sistema donde se intente ejecutar la aplicación. En nuestro caso lo dejamos tal cuál.

JVM Configuration.

Y llegamos a la última sección, donde indicaremos algunas opciones para la máquina virtual de JAVA.

Las primeras, la memoria máxima y mínima que usará la aplicación en el cliente.

Y en el cuadro inferior podremos introducir más opciones mediante la introducción de pares ‘Clave-Valor’.

Build.

Una vez hecho esto, podremos pulsar sobre el icono de la rueda dentada para que se compile el proyecto y nos genere el .exe de nuestra aplicación.

Concurrencia en Java

Voy a iniciar mis andanzas en este blog con un tema complicado, la concurrencia.

La concurrencia en Java o en cualquier otro lenguaje es siempre un problema. Y lo es porque empiezas a jugar con unas reglas y según avanza la partida las reglas cambian, o eso es lo que parece. Porque el principal problema que enfrentamos cuando estamos codificando un proceso de forma que se ejecute con varios hilos simultáneos es el más temido entre los programadores: no poder reproducir la situación.

Realmente, ese es el resultado final, traído simplemente para escenificar el problema inicial, que no siempre se tiene en cuenta, las condiciones de ejecución de tu programa van a cambiar la forma de responder de tu código. Es culpa de lo que se conoce como condición de carrera: el resultado depende del orden en que se ejecuten los procesos concurrentes.

A lo largo de nuestra carrera profesional, muchos hemos pasado por el fantástico momento del mantenimiento correctivo de la aplicación. Es el momento en el que haces penitencia por los pecados cometidos durante el desarrollo. El momento en que te acuerda de aquello de «listo, esto funciona, subiendoooooo (a svn)». Que gracioso parecía hace unos meses, antes de que se produjese este error imposible, «lexe que 1+1 son 2 de toda la vida y ahora resulta que mi programa dice que son 2433453222».

En mantenimiento correctivo, el primer paso es «reproduce la incidencia». Pues te pones y resulta que no hay forma. Aquí viene en ayuda tuya lo que piensas del usuario. Y rechazas la incidencia. Pero la incidencia vuelve y esta vez con el fichero de trazas «JGL: después de calcular: a = 1, b=1, a+b = 3556122654». Mientras te estás frotando los ojos, pasa el listo de turno y te dice «eso va a ser el multithreading«…

Luego viene aquello de esto lo hemos probado mil veces…en una maquina aunque solo tiene un solo core y con un conjunto (reducido) de datos generados por nosotros.

Hipódromo Nacional de Maroñas | photo by jikatu

Y es que esa es una característica de la concurrencia, el resultado depende del orden de ejecución de los hilos y este orden varía según el hardware y las entradas que tengamos. Tenemos un sistema que funciona perfectamente en una maquina con un dual core y que recibe 20 entradas por minuto, se traslada a una maquina con 4 cpu y 8 cores cada una porque el trafico va a multiplicarse por 50. Y ahora el sistema es diferente, el orden de ejecución de los hilos ha cambiado radicalmente. Por esto, por las condiciones de carrera, es necesario sincronizar nuestros hilos para que no se pisen unos a otros.

Para poder hacerlo necesitamos conocer las reglas y necesitamos mecanismos que garanticen que un hilo no rompe lo que hace otro y además que el cambio de hilo sea visible al resto. a=a+b no se realiza en un solo paso. En el punto en que nos afecta, primero se hace a+b y después se hace a = esa suma. Para garantizar que se hace en un solo paso, tenemos los mecanismos que vamos a ver en los próximos artículos.

Van a ser una serie de artículos en los que iremos viendo diferentes mecanismos que nos van a permitir controlar procesos que se ejecuten mediante hilos.

Esta serie va a estar dividida en 4 bloques:

  • Lo básico
  • Las circunstancias particulares
  • Controlando la madeja
  • Deshaciendo los nudos

Además, iré al lio, prometo no enrollarme. Nos vemos. Aquí.