NetBeans 6

Publicado en Noticias, Recursos el 8 de December, 2007 por Lek. (3 comentarios)

La semana pasada (y se nos pasó) vio la luz la versión definitiva de NetBeans 6.

NetBeans es el entorno de desarrollo gratuito creado por Sun (que también tiene otros de pago) y para algunos muy superior al Eclipse (empezando por Matisse y el soporte para servicios web). Las principales novedades os las copio vilmente de Bitelia:

  • Creación de interfaces gráficos Java de forma sencilla: Obten un aspecto profesional, colocando y alineando componentes en un espacio de trabajo
  • Desarrollo Web visual y Java EE: Crea páginas que siguiendo los estándares de forma visual y utilizando Ajax, CSS y JSF. También se incluye un conjunto completo de herramientas para EJB.
  • Desarrollo móvil visual: Crea, prueba y depura tus interfaces gráficos para dispositivos móviles
  • Modelado UML visual: Separa el diseño del software de la implementación
  • Soporte para Ruby y Rails: Se incluye un potente editor y depurador de Ruby con autocompletado de código y soporte completo para Rails. También incorpora el runtime JRuby
  • Desarrollo C y C++: Completo editor de C y C++ con depurador, plantillas de proyecto y soporte para varias configuraciones de proyecto

Yo me lo descargué e instalé, pero a simple vista mi querido Eclipse es bastante superior… aunque necesites instalarle unos cuantos plugins de entrada. Así que salvo que tenga que hacer alguna aplicación de escritorio me temo que criará telarañas binarias en mi disco duro. Pero sobre gustos…

OutputStream defectuosos…

Publicado en Java el 6 de December, 2007 por Lek. (3 comentarios)

En el post anterior sobre la gestión de memoria de los StringBuffer parece que Fran y yo tenemos una concepción diferente del problema. A lo largo del día me acordé de uno de esos bugs estúpidos de la máquina virtual que la gente de Sun considera una feature. Vamos a suponer el siguiente código:

FileInputStream in = new FileInputStream (new File (m_fileName));

URL url = new URL ("http://blog.4bits.es");
URLConnection conn = url.openConnection ();
conn.setDoOutput (true);
conn.setDoInput (true);
OutputStream dos = conn.getOutputStream ();
byte[] buffer = new byte[2048];

int readLength;
while ((readLength = in.read (buffer)) != -1) {
    dos.write (buffer, 0, readLength);
    dos.flush ();
}

//sigue por acá

¿Qué ocurre si el fichero ocupa más de 32 megas de memoria? Pues que salvo que arranquemos la máquina virtual con más memoria que la de por defecto, nos cascará un OutOfMemory… ¿Pero no estamos haciendo un dos.flush (); (línea 13) que nos vacía la memoria del OutputStream? Pues no.

El OutputStream devuelto por una clase URLConnection tiene un bug, conocido desde los tiempos de Maricastaña, por el cual el flush simplemente no funciona. ¿Y qué dice Sun a eso? Que no es un bug, con 2 cojones. Si quieres que funcione tienes que buscarte la vida o limitarte a esos 32 escasos megas.

Optimizando la memoria con StringBuffer

Publicado en Java el 4 de December, 2007 por Lek. (11 comentarios)

Ayer Chuchi y yo gastamos buena parte del día en solucionar un pequeño problema con una aplicación. El programa debía procesar un fichero XML, pero cuando le metía un fichero de ~5 megas cascaba el temido error OutOfMemory de la muerte. Realizamos alguna pequeña optimización, eliminamos varias duplicaciones que había del fichero en memoria (nunca uséis Strings), pero nada importante…

Dando mil y una vueltas hemos comprobado que tanto StringBuffer como las clases similares (StringBuilder por ejemplo) tienen una gestión de la memoria patética. Lo siguiente es el código original de la máquina virtual:

void expandCapacity (int minimumCapacity) {
    int newCapacity = (value.length + 1) * 2;
    if (newCapacity < 0) {
        newCapacity = Integer.MAX_VALUE;
    } else if (minimumCapacity > newCapacity) {
        newCapacity = minimumCapacity;
    }

    char newValue[] = new char[newCapacity];
    System.arraycopy (value, 0, newValue, 0, count);
    value = newValue;
}

Como vemos, cuando necesita ampliar el array interno, dobla la capacidad que tuviera, salvo que se le indique un tamaño mayor. Lo lógico, aquí y en China, sería lo contrario, pero los chicos de Sun funcionan a otro nivel. Con esto nos podemos encontrar que tenemos el StringBuffer con sus ~5 megas de contenido, pero consumiendo más de 8 en memoria. Y no tiene solución a priori, salvo que sepamos de antemano el tamaño que vamos a tener (que no era nuestro caso). Pero una vez terminado de rellenar sí podemos recuperar esa memoria vacía con una sencilla línea de código:

StringBuffer sb = new StringBuffer ();
do {
    sb.append (porrón de datos);
} while (condición);

sb.trimToSize(); //Truco del almendruco

No es, a buen seguro, la mejor de las gestiones, pero es mejor que nada.