Wednesday, November 29, 2006

Arquitectura cliente-servidor con cliente J2ME e intercambio de datos entre capas basado en XML

Introducción

[1] Se plantea aquí el uso de XML para transporte de los datos entre las capas de negocios y de presentación, en particular para clientes desarrollados en J2ME. Se analizan las distintas posibilidades para el envío de datos y se expone una estructura para soportar la utilización de XML, así como una implementación. Se introduce además una herramienta creada por el autor para desarrollos de estas características.

El patrón DTO (Data Transfer Objects).

[1] Este patrón se ocupa de cómo se intercambian datos entre capas de una aplicación multi-capas o entre componentes de una aplicación distribuida. Se debe tener en cuenta que el acceso a datos desde un componente remoto muchas veces implica extraer información de más de una entidad de información. Y, en esa multiplicidad de comunicaciones solicitando datos, la performance de la aplicación se vería resentida. Formalmente entonces, el objetivo de este patrón es, solucionar la perdida de performance en componentes distribuidos que hacen llamadas remotas para acceder a datos de los objetos de negocios.

[2] Aquí llegamos a la definición de DTO. Un DTO es básicamente un objeto creado exclusivamente para transportar datos. Datos que pueden tener su origen en una o más entidades de información. Estos datos son incorporados a una instancia de un JavaBean. Y esta instancia puede ser pasada a través de la aplicación, localmente o, lo que es más importante, puede ser serializada y enviada a través de la red, de forma que los clientes puedan acceder a información del modelo desde un solo objeto y mediante una sola llamada.

[3] Un DTO normalmente no provee lógica de negocios o validaciones de ningún tipo. Solo provee acceso a las propiedades del bean. Algunos autores remarcan que el bean debe ser inmutable, dado que sus cambios no deben reflejarse en el sistema. Pero obviamente esto choca con la especificación de los JavaBean, que requiere que todos los atributos privados tengan sus métodos set y get.

[4] Como siempre la última palabra la tiene el desarrollador, que determinará la mejor manera de manejar la mutabilidad de los DTO en su aplicación. En cualquier caso y para terminar, los DTO deben ser considerados parte del modelo en tanto que son copias inmutables de los objetos de negocios.

Los objetos DTO y la API J2ME

[1] La serialización es básicamente el proceso por el cual transformamos un objeto en un flujo de bytes para mandarlo a algún lado. Para una vez llegado allí, volver a re-armarlo como objeto y utilizarlo localmente.

[2] Debido a la ausencia en J2ME tanto de soporte para serialización como de soporte para reflexión, (mecanismo mediante el cual los propios objetos son capaces de inspeccionarse a sí mismos, averiguando sus métodos, atributos, parámetros, constructores, etc.) la serialización que se puede llevar a cabo debe ser desarrollada ad-hoc y adolecerá de ciertas limitaciones. Esto es, no podrá ser totalmente automatizada.

[3] Para lograr una serialización en J2ME el desarrollador deberá crear una interface serializable, con métodos como writeObject y readObject. Y hacer luego que sus objetos DTO la implementen. Esto es, deberá proveer implementaciones especializadasde esos métodos, para cada objeto.

[4] Si tuviéramos un objeto con los siguientes atributos:

[5]

   long puerto;
long bb;
String ruta;
int x;

[6] Los métodos para su serialización serían:

[7]

   public void writeObject(ObjectOutputStream out) throws IOException{
out.writeLong(puerto);
out.writeLong(bb);
out.writeInt(cc);
out.writeUTF(ruta);
out.writeInt(x);
}
public void readObject(ObjectInputStream in) throws IOException{
puerto = in.readLong();
bb = in.readLong();
cc = in.readInt();
ruta = in.readUTF();
x = in.readInt();
}

[8] Nótese que ambos métodos implican a las clases ObjectInputStream y ObjectOutputStream que también deben ser creadas y que extienden de DataInputStream y de DataOutputStream respectivamente. Y poseen, por lo tanto, los métodos de estas (para, agregar-al/extraer-del, flujo los distintos tipos de datos) y además métodos propios para leer objetos desde un flujo readObject() (la clase ObjectInputStream ) y para escribirlos en él, writeObject(Serializable object) (de la clase ObjectOutputStream ) que utilizan obviamente los métodos readObject y writeObject de la interface serializable .

[9] Para más información sobre serialización de objetos en J2ME se puede consultar [1]. Y en [5] se puede encontrar un excelente artículo en espa�ol. Y también es muy interesante el planteo de [6] relativo a la performance de los distintos algoritmos de serialización (recursivos y no recursivos) en J2ME.

Objetos XML

[1] Siendo que los objetos DTO por definición no llevan lógica y que J2ME no ofrece un mecanismo de serialización que nos haga transparente el intercambio de objetos aparece como una opción, muy razonable, la utilización de XML para codificar a los objetos de intercambio. Y es que además de que la implementación de un mecanismo Objeto-XML-Objeto no diferiría demasiado de los visto para serialización de objetos, tendríamos la ventaja adicional de que el XML resulta legible, tanto por ordenadores, como por seres humanos. Y su utilización, como veremos luego, facilitaría enormemente las tareas de debugging, dado que para generar instancias distintas de un mismo objeto bastaría con editar a mano el archivo XML.

[2] Cualquier browser, además, serviría para enviar un request al servidor y observar, en el mismo, la respuesta. Y es que si bien nuestra finalidad, en este caso puntual, es el desarrollo de un cliente en J2ME, poder chequear de un vistazo que la respuesta del servidor sea la apropiada es siempre una herramienta de debugging muy interesante. Y por último cabe destacar que la utilización de XML posibilita a nuestra aplicación dar respuesta tanto a clientes J2ME como J2SE (o páginas JSP) o .NET o lo que fuere.

[3] Lógicamente el uso de XML conlleva actividades de parseo y análisis sintáctico cuyo desarrollo es mejor, si se puede, evitar. En J2ME si bien la API, por supuesto, tampoco trae facilidades para tratar con XML, se puede disponer de un framework que resuelve estos asuntos en muy pocos Kb. La librería en cuestión se llama KXML [2].

Implementación del intercambio de datos entre cliente-servidor basado en XML

El proceso de desarrollo

[1] Una de las cosas importantes a resolver cuando se desarrolla un proyecto multi-capas es la definición de los objetos de intercambio de datos entre las capas de presentación y de negocios. Estos objetos de intercambio, lógicamente, estarán fuertemente condicionados por la "vista" que se desea obtener en el cliente.

[2] Una vez acordados, los ingenieros de back-end construirán los servicios que devolverán esos objetos y los ingenieros de front-end se abocarán a construir el cliente que los consumirá. Este es el punto exacto donde pueden empezar los problemas en el equipo. Esto es, si la capa de presentación, debe esperar por la de negocios para probar el cliente pueden surgir demoras indeseadas. Para esto la mejor solución es, luego de acordados los objetos de intercambio (DTO) encontrar la forma de generar objetos mock que nos provean a pedido los objetos que necesitamos para probar nuestro cliente.

[3] Durante un desarrollo reciente desarrollé una herramienta, MockMe, muy sencilla y adaptable que puede bajarse de [3] y en tanto que es un proyecto Open Source, puede ser modificado como se desee. Se trata básicamente de un servlet configurable a base de archivos .properties que busca XML de un directorio local, en función de un parámetro que se le pasa en la request. Lo dicho, muy fácil y muy efectivo a la hora de despegarnos de los tiempos de desarrollo de la capa de negocios. And last but no least, de la disponibilidad de datos específicos también. En [3] además de la propia herramienta y algunos XMLs de ejemplo puede obtenerse información sobre su instalación y configuración.

Separando objetos

[1] En parte a partir del requisito de inmutabilidad deseable en los DTO y en parte por una cuestión de prolijidad y organización en nuestro desarrollo, es conveniente tener dos tipos de objetos para cada entidad de información, esto es: objetos locales y objetos DTO.

[2] Por ejemplo, si utilizáramos internamente un objeto Persona y necesitáramos enviar sus datos, allende la JVM, deberíamos tener también PersonaDTO, que sería la versión de persona que circularía a través de la red (en XML). Es decir, si el servidor nos enviara un objeto Persona este nos llegaría en XML y al extraerlo obtendríamos un objeto PersonaDTO

[3] En el caso puntual de nuestra arquitectura, al haber optado por utilizar XML como soporte, la conversión de nuestros datos quedaría:

[4] ObjetoDTO-XML-ObjetoDTO

[5]

Arquitectura del cliente

[1] La arquitectura del cliente es conveniente que esté basada en algunos patrones típicos. El MVC para, mediante un objeto Controller [4], generar las vistas obteniendo los datos del Modelo a partir de la invocación de métodos de un objeto Facade que a su vez encapsule las peticiones. Llamando tanto al Modelo Local (almacenamiento RMS) como al Modelo Remoto (http) según toque.

[2]

Implementación

[1] Para implementar la transferencia de datos vía XML es útil hacer que nuestros objetos implementen ciertas interfaces. En el caso de los objetos de negocios es útil hacerlos extender de una interface como la siguiente:

[2]

     
public String toShow();
public String toRequestString();

[3] El método toShow() es útil para la visualización del objeto en la interfaz de usuario (así como para tareas de debugging). Y el método toRequestString() es necesario para que desarrolle el URL encoding que genere el request para ese objeto. A continuación ejemplos de ambos:

[4]

    public String toShow() {
Calendar cal = Calendar.getInstance();
cal.setTime(getFecha());
String txt = "Censo = " + getCenso()
+" \nFecha fichaje = " + FechaUtil.formatDate(getFecha())
+" \nJornada de comienzo = " + getJornadaComienzo()
+" \nJornadas = " + getTurnos()
+" \nSustituye = " + (isReemplaza()? "SI":"NO");
return txt;
}

[5]

   public String toRequestString() {
StringBuffer buff = new StringBuffer();
buff.append("codoper=" + getCodoper()
+ "&jornadacomienzo=" + getJornadaComienzo()
+ "&turnos=" + getTurnos()
+ "&reemplaza=" + isReemplaza()
+ "&movil=" + getMovil());
return buff.toString();
}

[6] En la siguiente Figura se grafica su utilización:

[7]

[8] El proceso de recibir la respuesta del servidor y transformarla en un objeto se ve en la Fig. 4. Y consta de una serie de pasos intermedios, implementados por métodos del Modelo Remoto.

[9]

Los objetos DTO

[1] Siendo que los objetos circularan entre capas como flujos XML, estos objetos DTO deberán tener métodos tanto para extraer los datos del objeto como, a la inversa, para darle estado al objeto a partir de un conjunto de valores encapsulados en una Hashtable. Nos resultará necesario definir un contrato con ellos. A continuación la interface para los objetos DTO:

[2]

  
public void populateFields(Hashtable fields)
Hashtable extractFields()

[3] El hecho de que implementen esta interface nos sería Útil también, para simplificar la recuperación de los objetos utilizando el polimorfismo.

[4] Si, por ejemplo, trataramos con un objeto Persona que tuviera los siguientes atributos:

[5]

    

id
fechaNacimiento
estado
experiencia
direccion
pais

[6] Una implementación factible para los métodos anteriores sería la siguiente:

[7]

   public void populateFields(Hashtable fields) {
this.id = (String) fields.get("id");
this.fechaNacimiento = new Date(Long.parseLong((String)fields.get("fechaNacimiento")));
this.estado = Integer.parseInt((String)fields.get("estado"));
this.experiencia = Integer.parseInt((String)fields.get("experiencia"));
this.direccion = (String) fields.get("direccion");
this.pais = (String) fields.get("pais");
}

public Hashtable extractFields() {
Hashtable fields = new Hashtable();
fields.put("id", this.censo);
fields.put("fechaNacimiento", "" + this.fechaNacimiento.getTime());
fields.put("estado", "" + this.estado);
fields.put("experiencia", "" + this.experiencia);
fields.put("direccion", this.direccion);
fields.put("pais", this.pais);
return fields;
}

[8] El método A de la figura, podría implementarse como sigue (backendComms()). Será el encargado de abrir la conexión con el servidor (sus parámetros de entrada son la URL del servidor y la request ) y de devolver un objeto String con el XML.

[9]

  public static String backendComms(String requestURL, String requeststring) throws ApplicationException
{
hc = null;
dis = null;
StringBuffer messagebuffer = new StringBuffer();
String requestString = requestURL + requeststring;
try {
hc = (HttpConnection) Connector.open(requestString,Connector.READ_WRITE, true);
hc.setRequestMethod(HttpConnection.GET);
hc.setRequestProperty("User-Agent","Profile/MIDP-2.0 Configuration/CLDC-1.1");
hc.setRequestProperty("Content-Language", "es-ES");
dis = new DataInputStream(hc.openInputStream());
int ch;
long len = hc.getLength();
if (len != -1) {
for (int i = 0; i < len; i++) {
if ((ch = dis.read()) != -1) {
messagebuffer.append((char) ch);
}
}
} else {
while ((ch = dis.read()) != -1) {
messagebuffer.append((char) ch);
}
}
dis.close();
} catch (InterruptedIOException iioe) {
messagebuffer = new StringBuffer("Time-out en la red.");
throw new ApplicationException(messagebuffer.toString());
} catch (IOException ioe) {
messagebuffer = new StringBuffer("Problema de servidor caído. Intente luego");
throw new ApplicationException(messagebuffer.toString());
} catch (ApplicationException ae) {
messagebuffer = new StringBuffer("Proceso interrumpido.");
throw new ApplicationException(messagebuffer.toString());
} catch (Exception e) {
messagebuffer = new StringBuffer("Problema de red. Intente luego");
throw new ApplicationException(messagebuffer.toString());
}finally {
cerrarConexion();
}
return messagebuffer.toString();
}

[10] Luego de obtenido el String con el XML debemos extraer de él, el IObjectDTO que corresponda. Es claro que además de los datos pertinentes, el XML deberá identificar la implementación de IObjectDTO a la que correspondan esos datos.

[11] En nuestro ejemplo lo haremos en dos pasos. Primero se parsearía el XML en forma genérica para obtener un objeto usando la interface IObjectDTO. Y luego por casting se lo llevaría al objeto esperado.

[12] El parseo del XML, como veremos más adelante, requerirá de una clase XMLUtil que utilizará la API provista por KXML.

[13] Supongamos por ejemplo que deseamos obtener un objeto del tipo PersonaDTO. En el modelo, se tendrán distintos métodos para obtener los distintos objetos DTO. Para este caso utilizaremos uno llamado getPersona().

[14]

  public PersonaDTO getPersona(Persona _persona) throws ApplicationException
{
StringBuffer requestString = new StringBuffer();
String tempStr = QUESTION + _persona.toRequestString();
requestString.append(tempStr);
String xml = backendComms(LOAD_URL, requestString.toString());
PersonaDTO personaDTO = convertXMLToPersonaDTO(xml);
return personaDTO;
}

[15] En la línea en negrita vemos la llamada al método C de la Figura 4. Que hace el casting, luego de llamar al método que extrae el objeto del XML (convertXMLToIObjectDTO(String xml)).

[16]

  private static PersonaDTO convertXMLToPersonaDTO(String _xml) {
PersonaDTO persona = (PersonaDTO)convertXMLToIObjectDTO(_xml);
return persona;
}

[17] Este que sigue sería entonces el método B de la Figura 4, que es el que utiliza la clase XMLutil para parsear el XML:

[18]

 
private static IObjectDTO convertXMLToIObjectDTO(String xml) {
InputStreamReader isr = new InputStreamReader(new ByteArrayInputStream(xml.getBytes()));
IObjectDTO ioDto = null;
try {
ioDto = XMLUtil.getObjectFromXML(isr);
} catch (IOException ioe) {
System.out.println("Problemas generando el objeto IObjectDTO");
ioe.printStackTrace();
}
return ioDto;
}

[19] Aquí una implementación posible para la clase XMLUtil

[20]

  public class XMLUtil {
public static IObjectDTO getObjectFromXML(InputStreamReader insr) throws IOException
{
IObjectDTO obj = null;
XmlParser parser = new XmlParser(insr);
Document document = new Document();
document.parse(parser);
// Para mostrar el contenido del documento XML en la consola
// usar document.write( new XmlWriter( new OutputStreamWriter(
// System.out) ) );
Element objectElement = document.getElement("object");
obj = getObjectFromXMLElement(objectElement);
return obj;
}

public static IObjectDTO getObjectFromXMLElement(Element objectElement)
{
String className = getTextFromElement(objectElement, "classname");
Element fieldsElement = objectElement.getElement("fields");
int childCount = fieldsElement.getChildCount();
Hashtable fields = new Hashtable();
Element fieldElement = null;
for (int i = 0; i < childCount; i++) {
if (fieldsElement.getType(i) == Xml.ELEMENT) {
fieldElement = fieldsElement.getElement(i);
String fieldName = getTextFromElement(fieldElement, "name");
// El campo es un objeto
if (fieldElement.getElement("value").getAttributeCount() > 0) {
IObjectDTO object = getObjectFromXMLElement(fieldElement.getElement("value").getElement("object"));
fields.put(fieldName, object);
}
// El campo es un String
else {
String fieldValue = stripCData(getTextFromElement(fieldElement,"value"));
fields.put(fieldName, fieldValue);
}
}

}
// Crear el objeto especificado en classname
IObjectDTO obj = null;
try {
Class clase = Class.forName(className);
obj = (IObjectDTO) clase.newInstance();
obj.populateFields(fields);
} catch (Exception e) {
System.out.println("Excepción al crear la clase: " + e.getMessage());
e.printStackTrace();
}
return obj;
}

public static StringBuffer getXMLFromObject(IObjectDTO object, int level) throws IOException {
StringBuffer objectToXML = new StringBuffer();
String tabs = "";
Class clase = object.getClass();
String className = clase.getName();
// Obtener número de tabs
for (int i = 0; i < level; i++)
tabs += "\t\t\t\t";
// Si es el inicio de un documento, mostrar la cabecera xml
if (level == 0)
objectToXML.append("\n\n");
// Mostrar los datos del objeto
objectToXML.append(tabs + "\n");
objectToXML.append(tabs + "\t" + className + "\n");
objectToXML.append(tabs + "\t\n");
Hashtable campos = object.extractFields();
Enumeration e = campos.keys();
while (e.hasMoreElements()) {
Object key = e.nextElement();
objectToXML.append(tabs + "\t\t\n");
objectToXML.append(tabs + "\t\t\t" + key + "\n");
if (campos.get(key) instanceof String) {
objectToXML.append(tabs + "\t\t\t\n");
} else if (campos.get(key) instanceof IObjectDTO) {
objectToXML.append(tabs + "\t\t\t\n");
objectToXML.append(getXMLFromObject((IObjectDTO) campos.get(key), level + 1));
objectToXML.append(tabs + "\t\t\t
\n");
}
objectToXML.append(tabs + "\t\t
\n");
}
objectToXML.append(tabs + "\t
\n");
objectToXML.append(tabs + "
\n");
return objectToXML;
}

private static String getTextFromElement(Element elementRoot, String elementName) {
String returnText = elementRoot.getElement(elementName).getText();
return returnText;
}

private static String stripCData(String value) {
String prefix = " String sufix = "]]>";
if (value.indexOf(prefix) >= 0)
value = value.substring(value.indexOf(prefix) + prefix.length());
if (value.indexOf(sufix) >= 0)
value = value.substring(value.indexOf(sufix));
return value;
}
}

[21] Como vemos, la clase XMLUtil utiliza ambos métodos de la interface IObjectsDTO (populateFields(Hashtable fields) y extractFields()) para las conversiones (XML a Objeto) y (Objeto a XML) respectivamente. Y se utiliza consecuentemente tanto del lado del cliente como del lado del servidor.

[22] Finalmente vemos un ejemplo de XML (en este caso enviado por el servidor como resultado de una operación de login):

[23]

 

org.lm2a.bebay.dtoobjects.LoginDTO


version



numMensajes



mensaje



fechaAccion



codigo




[24] Una vez construidas las clases (XMLUtil) y los métodos de soporte genéricos (backendComms), para el agregado de nuevos objetos solo deben ser creadas sus clases (que implementarán IobjectDTO) y los métodos para invocar los servicios que los devuelvan (tanto en Facade como en el Modelo Remoto).

Recursos

[1] Object Serialization in CLDC-Based Profiles. , http://java.sun.com/developer/J2METechTips/2002/tt0226.html#tip2
[2] KXML website. , http://kxml.objectweb.org/
[3] Proyecto MockMe. , http://mario.lamenza.googlepages.com/home
[4] J2EE Patterns Roadmap. , http://java.sun.com/developer/technicalArticles/J2EE/patterns/J2EEPatternsRoadmap.html
[5] Celeste Campo Vazquez, Rosa Ma Garcıa Rioja, Guillermo Diez-Andino Sancho, "Desarrollo de un mecanismo de serializacion en J2ME". , http://www.it.uc3m.es/celeste/papers/Serializacion.pdf
[6] Antonio J. Sierra, Recursive and non-recursive method to serialize object at J2ME. , http://www.w3.org/2006/02/Sierra10022006.pdf

Code Conventions for the Java Programming Language

1 Introduction

1.1 Why Have Code Conventions
1.2 Acknowledgments

2 File Names

2.1 File Suffixes
2.2 Common File Names

3 File Organization

3.1 Java Source Files

3.1.1 Beginning Comments
3.1.2 Package and Import Statements
3.1.3 Class and Interface Declarations

4 Indentation

4.1 Line Length
4.2 Wrapping Lines

5 Comments

5.1 Implementation Comment Formats

5.1.1 Block Comments
5.1.2 Single-Line Comments
5.1.3 Trailing Comments
5.1.4 End-Of-Line Comments
5.2 Documentation Comments

6 Declarations

6.1 Number Per Line
6.2 Initialization
6.3 Placement
6.4 Class and Interface Declarations

7 Statements

7.1 Simple Statements
7.2 Compound Statements
7.3 return Statements
7.4 if, if-else, if else-if else Statements
7.5 for Statements
7.6 while Statements
7.7 do-while Statements
7.8 switch Statements
7.9 try-catch Statements

8 White Space

8.1 Blank Lines
8.2 Blank Spaces

9 Naming Conventions

10 Programming Practices

10.1 Providing Access to Instance and Class Variables
10.2 Referring to Class Variables and Methods
10.3 Constants
10.4 Variable Assignments
10.5 Miscellaneous Practices

10.5.1 Parentheses
10.5.2 Returning Values
10.5.3 Expressions before `?' in the Conditional Operator
10.5.4 Special Comments

11 Code Examples

11.1 Java Source File Example

Monday, November 27, 2006

Novedades en Java 1.5

Autor: Ignacio Iborra
© Departamento de Ciencia de la Computación e Inteligencia Artificial, Universidad de Alicante, 2004

1. Introducción

En este documento se resumen las principales novedades que ofrece la versión 1.5 de Java, separándolas en diferentes áreas. Para una explicación más detallada, consultar la página de Sun:

http://java.sun.com/j2se/1.5.0/docs/relnotes/features.html

2. Novedades en la máquina virtual

Autoajuste de memoria mejorado

La capacidad de autoajustar la cantidad de memoria necesaria (pila, recolector de basura, etc) se ve mejorada en esta versión.

Compartir clases

Al instalar la máquina virtual, se cargan en memoria un conjunto de clases del sistema, en forma de representación interna, de forma que las siguientes llamadas a la máquina virtual ya encuentren estas clases mapeadas en memoria, y se permita que los datos de estas clases se compartan entre múltiples procesos dentro de la JVM.

Ajuste del recolector de basura

Relacionado con el autoajuste de memoria, el recolector de basura también se autoadapta a las necesidades de memoria de la aplicación, para evitar que el usuario tenga que ajustar su tamaño y características desde línea de comandos.

Tratamiento de errores fatales

El mecanismo de listado de errores fatales se ha mejorado de forma que se obtengan mejores diagnósticos a partir de las salidas generadas por dichos errores.

3. Novedades en el lenguaje

Tipos de datos parametrizados (generics)

Esta mejora permite tener colecciones de tipos concretos de datos, lo que permite asegurar que los datos que se van a almacenar van a ser compatibles con un determinado tipo o tipos. Por ejemplo, podemos crear un Vector que sólo almacene Strings, o una HashMap que tome como claves Integers y como valores Vectors. Además, con esto nos ahorramos las conversiones cast al tipo que deseemos, puesto que la colección ya se asume que será de dicho tipo.

Ejemplo

// Vector de cadenas
Vector v = new Vector();
v.addElement("Hola");
String s = v.getElementAt(0);
v.addElement(new Integer(20)); // Daría error!!

// HashMap con claves enteras y valores de vectores
HashMap hm = new HashMap();
hm.put(1, v);
Vector v2 = hm.get(1);

Autoboxing

Esta nueva característica evita al programador tener que establecer correspondencias manuales entre los tipos simples (int, double, etc) y sus correspondientes wrappers o tipos complejos (Integer, Double, etc). Podremos utilizar un int donde se espere un objeto complejo (Integer), y viceversa.

Ejemplo

Vector v = new Vector();
v.addElement(30);
Integer n = v.getElementAt(0);
n = n+1;

Mejoras en bucles

Se mejoran las posibilidades de recorrer colecciones y arrays, previniendo índices fuera de rango, y pudiendo recorrer colecciones sin necesidad de acceder a sus iteradores (Iterator).

Ejemplo

// Recorre e imprime todos los elementos de un array
int[] arrayInt = {1, 20, 30, 2, 3, 5};
for(int elemento: arrayInt)
System.out.println (elemento);

// Recorre e imprime todos los elementos de un Vector
Vector v = new Vector();
for(String cadena: v)
System.out.println (cadena);

Tipo enum

El tipo enum que se introduce permite definir un conjunto de posibles valores o estados, que luego podremos utilizar donde queramos:

Ejemplo

// Define una lista de 3 valores y luego comprueba en un switch
// cuál es el valor que tiene un objeto de ese tipo

enum EstadoCivil {soltero, casado, divorciado};
EstadoCivil ec = EstadoCivil.casado;
ec = EstadoCivil.soltero;
switch(ec)
{
case soltero: System.out.println("Es soltero");
break;
case casado: System.out.println("Es casado");
break;
case divorciado:System.out.println("Es divorciado");
break;
}

Imports estáticos

Los imports estáticos permiten importar los elementos estáticos de una clase, de forma que para referenciarlos no tengamos que poner siempre como prefijo el nombre de la clase. Por ejemplo, podemos utilizar las constantes de color de la clase java.awt.Color, o bien los métodos matemáticos de la case Math.

Ejemplo

import static java.awt.Color;
import static java.lang.Math;

public class...
{
...
JLabel lbl = new JLabel();
lbl.setBackground(white); // Antes sería Color.white
...
double raiz = sqrt(1252.2); // Antes sería Math.sqrt(...)
}

Argumentos variables

Ahora Java permite pasar un número variable de argumentos a una función (como sucede con funciones como printf en C). Esto se consigue mediante la expresión "..." a partir del momento en que queramos tener un número variable de argumentos.

Ejemplo

// Funcion que tiene un parámetro String obligatorio
// y n parámetros int opcionales


public void miFunc(String param, int... args)
{
...
// Una forma de procesar n parametros variables
for (int argumento: args)
{
...
}
...
}

...
miFunc("Hola", 1, 20, 30, 2);
miFunc("Adios");

Metainformación

Se tiene la posibilidad de añadir ciertas anotaciones en campos, métodos, clases y otros elementos, que permitan a las herramientas de desarrollo o de despliegue leerlas y realizar ciertas tareas. Por ejemplo, generar ficheros fuentes, ficheros XML, o un Stub de métodos para utilizar remotamente con RMI.

Un ejemplo más claro lo tenemos en las anotaciones que ya se utilizan para la herramienta Javadoc. Las marcas @deprecated no afectan al comportamiento de los métodos que las llevan, pero previenen al compilador para que muestre una advertencia indicando que el método que se utiliza está desaconsejado. También se tienen otras marcas @param, @return, @see, etc, que utiliza Javadoc para generar las páginas de documentación y las relaciones entre ellas.

Ejemplo

// Definición de una interfaz mediante metainformacion

public @interface MiInterfaz
{
int metodo1();
String metodo2();
}

4. Novedades en librerías principales

Red

Se han añadido cambios y mejoras para el trabajo en red, como:

  • Soporte para IPv6 en Windows XP y 2003
  • Establecimiento de timeouts para conectar y leer
  • API para lanzar aplicaciones RMI a través de inetd
  • La clase InetAddress permite testear si una URL es alcanzable (utilidad ping)
  • Otras mejoras en el tratamiento de cookies, servidores proxy, tratamiento de URLs, etc.

Seguridad

Hay bastantes mejoras en seguridad. Se da soporte a más estándares de seguridad (SASL, OCSP, TSP, etc), hay mejoras en la escalabilidad a través de SSLEngine, en criptografía, etc.

Internacionalización

Mediante la internacionalización podemos construir una aplicación que se adapte a varios idiomas, formatos monetarios, de fecha, etc, sin tener que reprogramarla. En este aspecto, se añaden mejoras en la versión 1.5, relacionadas con:

  • La gestión de juegos de caracteres se basa en el formato Unicode 4.0, lo que afecta a las clases Character y String, entre otras.
  • La clase DecimalFormat se ha modificado para poder procesar elementos de tipo BigDecimal o BigInteger sin perder precisión
  • Se han añadido nuevos Locales soportados, como el vietnamita.

Formateador

La clase Formatter permite dar formato (justificación y alineamiento, formatos numéricos, de fecha, etc) a las cadenas y otros tipos de datos, siguiendo un estilo parecido al printf de C. También se permite mediante la interfaz Formattable dar formatos (limitados) a tipos creados por el usuario.

Ejemplo

// Uso de formatter para construir cadenas formateadas
StringBuilder sb = new StringBuilder();
Formatter f = new Formatter(sb, Locale.US);
f.format("Hola, %1$2s, esta es tu visita numero %2$d", "Pepe", 20);
// Resultaría: "Hola, Pepe, esta es tu visita numero 20"

// También se tienen unos métodos predefinidos en ciertas clases
System.out.format("Hola, %1$2s, esta es tu visita numero %2$d", "Pepe", 20);
System.err.printf("Hola, %1$2s, esta es tu visita numero %2$d", "Pepe", 20);
String s = String.format("Hola, %1$2s", "Pepe");

Escaneador

La clase Scanner permite parsear un flujo de entrada (fichero, cadena de texto, stream de datos, etc), y extraer tokens siguiendo un determinado patrón o tipo de datos. También se permite trabajar con expresiones regulares para indicar qué patrones se deben buscar.

Ejemplo

// Lectura de enteros de la entrada estándar
Scanner sc = Scanner.create(System.in);
int n = sc.nextInt();

// Lectura de todos los doubles de un fichero
Scanner sc = Scanner.create(new File("miFich.txt"));
while (sc.hasNextDouble())
double d = sc.nextDouble();

// Uso de otros delimitadores
String s = "Esto hola es hola 1 hola ejemplo";
Scanner sc = Scanner.create(s).useDelimiter("\\s*hola\\s*");
System.out.println(sc.next());
System.out.println(sc.next());
System.out.println(sc.next());
// Sacaría Esto \n es \n 1

Arquitectura de JavaBeans

La arquitectura de JavaBeans se encuentra dentro del paquete java.beans. Se ha añadido una nueva clase, IndexedPropertyChangeEvent, subclase de PropertyChangeEvent, para dar soporte a eventos que respondan a cambios en propiedades indexadas (propiedades que utilicen un índice para identificar la parte del bean que haya cambiado). También se han añadido mejoras a la hora de crear editores de propiedades de beans (PropertyEditor), como el método createPropertyEditor(...), y constructores públicos para la clase PropertyEditorSupport.

Arquitectura de colecciones

Como se ha comentado antes, las colecciones (estructura que contiene clases e interfaces como Collection, Vector, ArrayList, etc) dan soporte a nuevas características del lenguaje, como el autoboxing, mejoras en los bucles (for) , y el uso de generics. Además, se han añadido interfaces nuevos, como Queue, BlockingQueue y ConcurrentMap, con algunas implementaciones concretas de dichas interfaces. Además, se tienen nuevas implementaciones de List, Set y Map.

Manipulación de bits

Los wrappers de tipos simples (es decir, clases como Integer, Long, Double, Char) soportan operaciones de bits, como highestOneBit, lowestOneBit, rotateLeft, rotateRight, reverse, etc.

Elementos matemáticos

El paquete java.math también ha sufrido modificaciones, como la adición en la clase BigDecimal de soporte para cálculo en coma flotante de precisión fija. Clases como Math o StrictMath además incluyen soporte para senos y cosenos hiperbólicos, raíces cúbicas o logaritmos en base 10. Por último, también se da soporte al uso de números hexadecimales con coma flotante.

Serialización

Además de corregir errores previos en la serialización, se da soporte para serializar el nuevo tipo enum, aunque la forma de serializarlo difiere ligeramente de los tipos tradicionales.

Hilos

Se han añadido los paquetes java.util.concurrent, java.util.concurrent.atomic y java.util.concurrent.locks, que permiten crear diversas infraestructuras de hilos, como pooling de hilos o colas de bloqueos, liberando al programador de tener que controlar todas estas estructuras "a mano". En definitiva, se da soporte para automatizar la programación concurrente.

Además, a la clase Thread se le han añadido los métodos getStackTrace y getAllStackTraces para obtener la traza de los hilos en un momento dado.

Monitorización y gestión

Se tienen mejoras en el control o la monitorización tanto de las aplicaciones Java como de la máquina virtual (JVM), a través de la API de JMX.

5. Novedades en librerías adicionales

RMI

Se tienen dos mejoras fundamentales en RMI:

  • Generación dinámica de Stubs: se generan en tiempo de ejecución, sin necesidad de utilizar rmic previamente. Sólo tendremos que utilizarlo para generar Stubs para clientes que funcionen con versiones anteriores de Java.
  • Lanzamiento de rmid o un servidor RMI Java desde inetd/xinetd.

JDBC

En Java 1.4 se introdujo la interfaz RowSet, que permitía pasar datos entre componentes. En Java 1.5 se han desarrollado 5 implementaciones de dicha interfaz, para cubrir 5 posibles casos de uso:

  • JdbcRowSet: para encapsular un ResultSet o un driver que utilice tecnología JDBC
  • CachedRowSet: desconecta de la fuente de datos y trabaja independientemente, salvo cuando esté obteniendo datos de dicha fuente o volcando datos en ella.
  • FilteredRowSet: hereda de la anterior, y se utiliza para obtener un subconjunto de datos
  • JoinRowSet: hereda de CachedRowSet y se emplea para unir múltiples objetos RowSet.
  • WebRowSet: hereda de CachedRowSet para procesar datos XML.

JNDI

  • Mejoras en la clase javax.naming.NameClassPair para poder acceder al nombre completo del servicio de directorio.
  • Soporte para controles estándar de LDAP
  • Soporte para manipular nombres de LDAP

6. Novedades en la interfaz de usuario

Internacionalización

Para permitir renderizar texto multilingüe utilizando fuentes lógicas, se tienen en cuenta tanto las fuentes del cliente como las del locale que tengamos instalado. Además, AWT utiliza APIs Unicode en Windows 2000 y XP, con lo que se puede manejar texto sin estar limitado a la configuración de locale de Windows.

Java Sound

Para el tratamiento del sonido desde Java, se tienen también los siguientes cambios, principalmente:

  • Se permite el acceso a puertos en todas las plataformas
  • También está disponible la entrada/salida MIDI

Java 2D

  • Se cachean en memoria todas las imágenes construidas a partir de BufferedImage
  • Métodos para controlar la aceleración hardware en imágenes
  • Añadido soporte para aceleración hardware con OpenGL en Solaris y Linux.
  • Creación de fuentes a partir de ficheros y flujos de entrada
  • Se ha mejorado la renderización de texto.

Flujos de imágenes

Se permite, además de los formatos de imágenes ya soportados (PNG, JPG, etc), leer y escribir imágenes BMP y WBMP.

AWT

Las novedades más significativas son:

  • La clase MouseInfo almacena información sobre la posición del ratón en el escritorio
  • Se tienen nuevos métodos en la clase Window para especificar la posición para las nuevas ventanas que se creen. También se tienen métodos para asegurar que una ventana permanezca siempre en primer lugar (aunque esta característica no funciona bien en algunas versiones de Solaris o Linux)
  • Nuevos métodos para acceder y notificar sobre el contenido del portapapeles.
  • Se han corregido errores existentes en los layout managers: GridBagLayout y FlowLayout.
  • Cambios y correcciones en eventos de teclado (nuevos mapeos de teclas, redefinición de métodos, etc), y de acción (correcciones en cuanto al uso de Enter como evento de acción).

Swing

Entre otras, se tienen las novedades:

  • Se proporcionan nuevos look & feels (uno de ellos, Synth, es skinnable, es decir, se puede personalizar el skin que muestra)
  • Se añade soporte para imprimir JTables.
  • Se permite definir menús contextuales (popup menus) en componentes, para que muestren las opciones que queramos. Para ello se tiene la clase JPopupMenu.
  • Se han añadido mejoras en JTextArea para facilitar el scroll por su contenido, y la actualización cuando se modifique su texto.
  • Podremos utilizar el método JFrame.add(...), en lugar de JFrame.getContentPane().add(...)
// Antes
JFrame f = new JFrame();
f.getContentPane().add(new JButton("Hola"));

// Ahora
JFrame f = new JFrame();
f.add(new JButton("Hola"));

7. Novedades en despliegue de aplicaciones

Despliegue general

Se tienen, entre otras, las siguientes novedades en cuanto a despliegue de aplicaciones:

  • Se ha unido gran parte de la funcionalidad entre el Java Plug-in y Java Web Start, de modo que ahora tienen un Java Control Panel común para ambos
  • Las aplicaciones desplegadas se pueden configurar mediante un fichero de configuración, que puede ser accedido a través de una URL, y establecer ciertos parámetros de la aplicación.
  • El formato de compresión Pack200 permite tener ficheros JAR ultra-comprimidos (hasta 1/8 de su tamaño original), reduciendo los tiempos de descarga, o de despliegue mediante Java Web Start.
  • Inclusión de marcas de tiempo (timestamps) en los ficheros JAR firmados, de forma que se sabe cuándo se concedió el certificado para el fichero, y se previene así el uso de JARs cuyo permiso ya caducó.

Java Web Start

Hay también cambios específicos de Java Web Start, como son:

  • Supresión del Application Manager, cuya mayor funcionalidad se ha encapsulado dentro del nuevo Java Control Panel, y el JNLP Cache Viewer, una nueva herramienta que permite gestionar las aplicaciones descargadas.
  • Supersión del Developer Bundle, ya que Java Web Start está completamente integrado con JRE y SDK, y los elementos que contenía dicho bundle ahora están integrados en Java.
  • Se tiene una caché de sistema, de forma que el administrador del sistema puede cargar al inicio programas en la caché de sistema, de forma que sean compartidas y accesibles por múltiples usuarios.
  • Hay también una facilidad de importación, de forma que se facilita la instalación desde CDs, donde el código se carga primero desde un lugar y luego se actualiza desde otro. También permite preinstalar aplicaciones y librerías en caché, sin ejecutarlas.

8. Novedades en herramientas

JPDA

JPDA es un conjunto de interfaces utilizadas para depurar en entornos y sistemas de desarrollo. En la versión 1.5 se tienen nuevas mejoras y funcionalidades de esta herramienta. Muchas de estas nuevas funcionalidades se han añadido para adaptar las nuevas características de la versión 1.5 de Java, como los argumentos variables, imports estáticos, etc.

JVMTI

JVMTI (Java Virtual Machine Tool Interface) es una nueva interfaz de programación nativa para utilizar en herramientas de desarrollo y monitorización. Forma parte de las interfaces contenidas en JPDA para depuración. Permite chequear el estado y controlar la ejecución de una aplicación.

Compilador (javac)

Se han añadido algunas características a la hora de utilizar el compilador, como son los parámetros:

  • - source 1.5 : habilita las nuevas características de la versión 1.5 de Java, para ser tenidas en cuenta por el compilador. Lleva implícito también un parámetro -target 1.5
  • -target 1.5: permite al compilador utilizar características específicas de Java 1.5 en las librerías y la máquina virtual.
  • -Xlint: permite producir warnings sobre código que, aunque es correcto, puede ser problemático debido a su construcción.

Herramienta javadoc

Se tienen nuevas funcionalidades en la herramienta javadoc. Como en otros elementos, muchos de los cambios dan soporte a características nuevas de Java 1.5 (generics, tipo enum, etc). Se tienen también marcas nuevas, como regression para indicar funcionalidades que se desaconsejaron en versiones anteriores, pero que han sido corregidas en la nueva. También se da soporte a anotaciones para generar metainformación que utilizar en otros programas.

New Features and Enhancements J2SE 5.0

Java 2 Platform Standard Edition 5.0 is a major feature release. The features listed below are introduced in 5.0 since the previous major release (1.4.0).

For highlights of the new features, also see J2SETM 5.0 in a Nutshell. For issues, see JDK 5.0 release notes.

Performance Enhancements
Java Language Features
Generics
Enhanced for Loop
Autoboxing/Unboxing
Typesafe Enums
Varargs
Static Import
Metadata (Annotations)
Virtual Machine
Class Data Sharing
Garbage Collector Ergonomics
Server-Class Machine Detection
Thread Priority Changes
Fatal Error Handling
High-Precision Timing Support
Base Libraries
Lang and Util Packages
Networking
Security
Internationalization
Improved Support for Environment Variables
ProcessBuilder
Formatter
Scanner
Reflection
JavaBeansTM Component Architecture
Collections Framework
Java API for XML Processing (JAXP)
Bit Manipulation Operations
Math
Instrumentation
Serialization
Concurrency Utilities
Threads
Monitoring and Management
Integration Libraries
Remote Method Invocation (RMI)
Java Database Connectivity (JDBC)
CORBA, Java IDL, and Java RMI-IIOP
Java Naming and Directory InterfaceTM (JNDI)
User Interface
Internationalization
Java Sound Technology
Java 2DTM Technology
Image I/O
AWT
Swing
Deployment
General Deployment
Java Web Start
Tools and Tool Architecture
Java Virtual Machine Tool Interface (JVMTI)
Java Platform Debugger Architecture (JPDA)
Java Compiler (javac)
Javadoc Tool
Annotation Processing Tool (apt)
Java TM 2 Platform, Standard Edition 5.0 Trouble-Shooting and Diagnostic Guide
OS & Hardware Platforms
Supported System Configurations
64-Bit AMD Opteron Processors

Performance Enhancements

For a synopsis of performance enhancements, see Performance Enhancements.

JavaTM Language Features

For more information see New Language Features.

Generics

This long-awaited enhancement to the type system allows a type or method to operate on objects of various types while providing compile-time type safety. It adds compile-time type safety to the Collections Framework and eliminates the drudgery of casting. Refer to JSR 14.

Enhanced for Loop

This new language construct eliminates the drudgery and error-proneness of iterators and index variables when iterating over collections and arrays. Refer to JSR 201 .

Autoboxing/Unboxing

This facility eliminates the drudgery of manual conversion between primitive types (such as int) and wrapper types (such as Integer). Refer to JSR 201 .

Typesafe Enums

This flexible object-oriented enumerated type facility allows you to create enumerated types with arbitrary methods and fields. It provides all the benefits of the Typesafe Enum pattern ("Effective Java," Item 21) without the verbosity and the error-proneness. Refer to JSR 201.

Varargs

This facility eliminates the need for manually boxing up argument lists into an array when invoking methods that accept variable-length argument lists. Refer to JSR 201.

Static Import

This facility lets you avoid qualifying static members with class names without the shortcomings of the "Constant Interface antipattern." Refer to JSR 201.

Metadata (Annotations)

This language feature lets you avoid writing boilerplate code under many circumstances by enabling tools to generate it from annotations in the source code. This leads to a "declarative" programming style where the programmer says what should be done and tools emit the code to do it. Also it eliminates the need for maintaining "side files" that must be kept up to date with changes in source files. Instead the information can be maintained in the source file. Refer to JSR 175.

Virtual Machine

Class Data Sharing

The class data sharing feature is aimed at reducing application startup time and footprint. The installation process loads a set of classes from the system jar file into a private, internal representation, then dumps that representation to a "shared archive" file. During subsequent JVM invocations, the shared archive is memory-mapped in, saving the cost of loading those classes and allowing much of the JVM's metadata for these classes to be shared among multiple JVM processes. For more information, click the above link.

Garbage Collector Ergonomics

The parallel collector has been enhanced to monitor and adapt to the memory needs of the application. You can specify performance goals for applications and the JVM will tune the size of the Java heap to meet those performance goals with the smallest application footprint consistent with those goals. The goal of this adaptive policy is to eliminate the need to tune command-line options to achieve the best performance. For a synopsis of garbage collection features, click the above link.

Server-Class Machine Detection

At application startup, the launcher can attempt to detect whether the application is running on a "server-class" machine.

Thread Priority Changes

Thread priority mapping has changed somewhat allowing Java threads and native threads that do not have explicitly set priorities to compete on an equal footing.

Fatal Error Handling

The fatal error reporting mechanism has been enhanced to provide improved diagnostic output and reliability.

High-Precision Timing Support

The method System.nanoTime() has been added, providing access to a nanosecond-granularity time source for relative time measurements. The actual precision of the time values returned by System.nanoTime() is platform-dependent.

Base Libraries

Lang and Util Packages

For a synopsis of java.lang and java.util enhancements, click the above link.

Networking

For a synopsis of added networking features, click the above link.

Security

This release of J2SE offers significant enhancements for security. It provides better support for security tokens, support for more security standards (SASL, OCSP, TSP), improvements for scalability (SSLEngine) and performance, plus many enhancements in the crypto and Java GSS areas. For details see the above link.

Internationalization

Enhancements are as follows:
  • Character handling is now based on version 4.0 of the Unicode standard. This affects the Character and String classes in the java.lang package, the collation and bidirectional text analysis functionality in the java.text package, character classes in the java.util.regex package, and many other parts of the J2SE. As part of this upgrade, support for supplementary characters has been specified by the JSR 204 expert group and implemented throughout the J2SE. See the article Supplementary Characters in the Java Platform, the Java Specification Request 204, and the Character class documentation for more information.
  • The DecimalFormat class has been enhanced to format and parse BigDecimal and BigInteger values without loss of precision. Formatting of such values is enhanced automatically; parsing into BigDecimal needs to be enabled using the setParseBigDecimal method.
  • Vietnamese is now supported in all locale sensitive functionality in the java.util and java.text packages. See the Supported Locales document for complete information on supported locales and writing systems.

Improved Support for Environment Variables

The System.getenv(String) method is no longer deprecated. The new System.getenv() method allows access to the process environment as a Map.

ProcessBuilder

The new ProcessBuilder class provides a more convenient way to invoke subprocesses than does Runtime.exec. In particular, ProcessBuilder makes it easy to start a subprocess with a modified process environment (that is, one based on the parent's process environment, but with a few changes).

Formatter

An interpreter for printf-style format strings, the Formatter class provides support for layout justification and alignment, common formats for numeric, string, and date/time data, and locale-specific output. Common Java types such as byte, java.math.BigDecimal , and java.util.Calendar are supported. Limited formatting customization for arbitrary user types is provided through the java.util.Formattable interface.

Scanner

The java.util.Scanner class can be used to convert text into primitives or Strings. Since it is based on the java.util.regex package, it also offers a way to conduct regular expression based searches on streams, file data, strings, or implementors of the Readable interface.

Reflection

Have added support for generics, annotations, enums and have added convenience methods. Also have generified the class java.lang.Class.

JavaBeans Component Architecture

A subclass of PropertyChangeEvent called IndexedPropertyChangeEvent has been added to support bound properties that use an index to identify the part of the bean that changed. Also, methods have been added to the PropertyChangeSupport class to support firing indexed property change events.

Collections Framework

The Collections Framework has been enhanced in the following ways:
  • Three new language features are targeted at collections: Generics, Enhanced for Loop, and Autoboxing.
  • Three new interfaces have been added to the framework (two of which are part of java.util.concurrent): Queue, BlockingQueue, and ConcurrentMap.
  • Two concrete implementations of Queue have been added, as well as one skeletal implementation.
  • Five blocking queue implementations have been added, and one ConcurrentMap implementation.
  • Special-purpose Map and Set implementations are provided for use with typesafe enums.
  • Special-purpose copy-on-write List and Set implementations have been added.
  • Wrapper implementations are provided to add dynamic type-safety for most collection interfaces.
  • Several new algorithms are provided for manipulating collections.
  • Methods are provided to compute hash codes and string representations for arrays.

Java API for XML Processing (JAXP)

Click the above link for details or refer to JSR 206.

Bit Manipulation Operations

The wrapper classes (Integer, Long, Short, Byte, and Char) now support common bit manipulation operations which include highestOneBit, lowestOneBit, numberOfLeadingZeros, numberOfTrailingZeros, bitCount, rotateLeft, rotateRight, reverse, signum, and reverseBytes.

Math

The numerical functionality provided by the libraries has been augmented in several ways:
  • The BigDecimal class has added support for fixed-precision floating-point computation. Refer to JSR 13.
  • The Math and StrictMath libraries include hyperbolic transcendental functions (sinh, cosh, tanh), cube root, base 10 logarithm, etc.
  • Hexadecimal floating-point support - To allow precise and predictable specification of particular floating-point values, hexadecimal notation can be used for floating-point literals and for string to floating-point conversion methods in Float and Double.

Instrumentation

The new java.lang.instrument package provides services that allow Java programming agents to instrument programs running on the Java virtual machine. The intrumentation mechanism is modification of the bytecodes of methods.

Serialization

Support has been added to handle enumerated types which are new in version 5.0. The rules for serializing an enum instance differ from those for serializing an "ordinary" serializable object: the serialized form of an enum instance consists only of its enum constant name, along with information identifying its base enum type. Deserialization behavior differs as well--the class information is used to find the appropriate enum class, and the Enum.valueOf method is called with that class and the received constant name in order to obtain the enum constant to return.

Concurrency Utilities

The java.util.concurrent, java.util.concurrent.atomic, and java.util.concurrent.locks packages provide a powerful, extensible framework of high-performance, scalable, thread-safe building blocks for developing concurrent classes and applications, including thread pools, thread-safe collections, semaphores, a task scheduling framework, task synchronization utilities, atomic variables, and locks. The addition of these packages to the core class library frees the programmer from the need to craft these utilities by hand, in much the same manner that the Collections Framework did for data structures. Additionally, these packages provide low-level primitives for advanced concurrent programming which take advantage of concurrency support provided by the processor, enabling programmers to implement high-performance, highly scalable concurrent algorithms in the Java language to a degree not previously possible without resorting to native code. Refer to JSR 166 .

Threads

The java.lang.Thread class has the following enhancements:
  • Thread priority handling has changed; see the above link for details.
  • Thread.State enum class and the new getState() API are provided for querying the execution state of a thread.
  • The new thread dump API - the getStackTrace and getAllStackTraces methods in the Thread class - provides a programmatic way to obtain the stack trace of a thread or all threads.
  • The uncaughtExceptionHandler mechanism, previously available only through the ThreadGroup class, is now available directly through the Thread class.
  • A new form of the sleep() method is provided which allows for sleep times smaller than one millisecond.

Monitoring and Management

This release of J2SE offers significant enhancements for monitoring and management for the Java platform. See the above link for details.
  • Monitoring and management API for the Java virtual machine
    The new java.lang.management package provides the interface for monitoring and managing the Java virtual machine.
  • Monitoring and management API for the logging facility
    The new java.util.logging.LoggingMXBean interface is the management interface for the logging facility.
  • JMX instrumentation of the Java virtual machine
    The Java virtual machine (JVM) has built-in instrumentation that enables you to monitor and manage it using JMX. You can easily start a JMX agent for monitoring and managing remote or local Java VMs instrumentation or of any application with JMX instrumentation. See Monitoring and Management Using JMX for details.
  • The SNMP agent publishes the standard MIB for the Java virtual machine instrumentation as defined by JSR 163. For more information, see SNMP Monitoring and Management.
  • JavaTM Management Extensions
    JMXTM API version 1.2 and the RMI connector of the JMX Remote API version 1.0 are included in J2SE 5 release. The JMX API allows you to instrument libraries and applications for monitoring and management. The RMI connector allows this instrumentation to be remotely accessible. See the JMX documentation for more details.

Integration Libraries

Remote Method Invocation (RMI)

RMI has been enhanced in the following areas:
  • Dynamic Generation of Stub Classes - This release adds support for the dynamic generation of stub classes at runtime, obviating the need to use the Java Remote Method Invocation (Java RMI) stub compiler, rmic, to pregenerate stub classes for remote objects. Note that rmic must still be used to pregenerate stub classes for remote objects that need to support clients running on earlier versions.
  • Standard SSL/TLS Socket Factory Classes - This release adds standard Java RMI socket factory classes, javax.rmi.ssl.SslRMIClientSocketFactory and javax.rmi.ssl.SslRMIServerSocketFactory, which communicate over the Secure Sockets Layer (SSL) or Transport Layer Security (TLS) protocols using the Java Secure Socket Extension (JSSE).
  • Launching rmid or a Java RMI Server from inetd/xinetd - A new feature, provided by the System.inheritedChannel method, allows an application to obtain a channel (java.nio.channels.SocketChannel or java.nio.channels.ServerSocketChannel, for example) inherited from the process that launched the virtual machine (VM). Such an inherited channel can be used to either service a single incoming connection (as with SocketChannel) or accept multiple incoming connections (as with ServerSocketChannel). Therefore, Java networking applications launched by inetd (Solaris(tm) Operating System) or xinetd (Linux) can now obtain the SocketChannel or ServerSocketChannel inherited from inetd/xinetd.

Java Database Connectivity (JDBC)

RowSet interface, part of the javax.sql package, introduced in J2SE version 1.4, provides a lightweight means of passing data between components.

At this release, as an aid to developers, the RowSet interface has been implemented (as JSR 114) in five of the more common ways a RowSet object can be used. These implementations provide a standard that developers are free to use as is or to extend.

Following are the five standard implementations:

  • JdbcRowSet - used to encapsulate a result set or a driver that is implemented to use JDBC technology
  • CachedRowSet - disconnects from its data source and operates independently except when it is getting data from the data source or writing modified data back to the data source. This makes it a lightweight container for as much data as it can store in memory.
  • FilteredRowSet - extends CachedRowSet and is used to get a subset of data
  • JoinRowSet - extends CachedRowSet and is used to get an SQL JOIN of data from multiple RowSet objects
  • WebRowSet - extends CachedRowSet and is used for XML data. It describes tabular components in XML using a standardized XML schema.

CORBA, Java IDL, and Java RMI-IIOP

Enhancements to CORBA, Java IDL, and Java RMI-IIOP are discussed in Changes in CORBA Features Between J2SE 1.4.x and 5.0.

Java Naming and Directory InterfaceTM (JNDI)

JNDI provides the following new features.
  • Enhancements to javax.naming.NameClassPair to access the fullname from the directory/naming service
  • Support for standard LDAP controls: Manage Referral Control, Paged Results Control and Sort Control
  • Support for manipulation of LDAP names.

User Interface

Internationalization

  • To render multilingual text, using logical fonts, 2D now takes advantage of installed host OS fonts for all supported writing systems. For example, if you run in a Thai locale environment, but have Korean fonts installed, both Thai and Korean are rendered. The J2RE now also automatically detects physical fonts that are installed into its lib/fonts/fallback directory and adds these physical fonts to all logical fonts for 2D rendering.
  • AWT now uses the Unicode APIs on Windows 2000/XP. As a result, some of its components can handle text without being restricted by Windows locale settings. For example, AWT text components can accept and display text in the Devanagari writing system regardless of the Windows locale settings.

Java Sound Technology

  • Ports are now available on all platforms (RFE 4782900).
  • MIDI device i/o is now available on all platforms (RFE's 4812168, 4782924).
  • Optimized direct audio access is implemented on all platforms (RFEs 4908240 and 4908879). It is enabled by default on systems which offer native mixing (i.e. Linux ALSA with hardware mixing, Solaris Mixer enabled, Windows DirectSound).
  • The new real-time Sequencer works with all MIDI devices and allows unlimited Transmitters (RFE 4773012).
  • The sound.properties configuration file allows choice of default devices (RFE 4776511). For details, see MidiSystem and AudioSystem for details.
  • MidiDevices can query connected Receivers and Transmitters (RFE 4931387, methods MidiDevice.getReceiver and MidiDevice.getTransmitter).
  • AudioFormat, AudioFileFormat, and MidiFileFormat now have properties that allow further description and qualification of the format (RFEs 4925767 and 4666845).
  • A set of ease-of-use methods allow easier retrieval of lines from AudioSystem (RFE 4896221).
  • The Sequencer interface is extended with loop methods, for seamless looping of specific portions of a MIDI sequence (RFE 4204105).
  • Java Sound no longer prevents the VM from exiting (bug 4735740).

Java 2DTM Technology

Added 2D features include expanded Linux and Solaris printer support, new methods for creating fonts from files and streams, and new methods related to VolatileImages and hardware acceleration of images. A number of internal changes to text rendering code greatly improve its robustness, performance, and scalability. Other performance work includes hardware-accelerated rendering using OpenGL (disabled by default).

Image I/O

The Image I/O system now has readers and writers for BMP and WBMP formats.

AWT

Version 5.0 features many AWT enhancements and bug fixes, including some that have often been requested by our customers. Most notably, the new MouseInfo class makes it possible to determine the mouse location on the desktop. New Window methods make it possible to specify the default location for a newly created window (or frame), appropriate to the platform. Another Window enhancement makes it possible to ensure that a window (or frame) is always on top. (This feature does not work for some window managers on Solaris/Linux.) In the area of data transfer, the new DropTargetDragEvent API allows the drop target to access transfer data during the drag operation.

Swing

With the 1.4.2 release we provided two new look and feels for Swing: XP and GTK. Rather than taking a break, in 5.0 we're providing two more look and feels: Synth, a skinnable look and feel, and Ocean, a new theme for Metal. Beyond look and feels, we've added printing support to JTable, which makes it trivial to get a beautiful printed copy of a JTable. Lastly, after seven years, we've made jFrame.add equivalent to jFrame.getContentPane().add().

Deployment

General Deployment

Pack200, a new hyper-compression format for JAR files defined by JSR 200, can significantly reduce the download size of JAR files used in Java Webstart applications and Java Plug-in applets.

For a synopsis of general deployment features and enhancements, click the General Deployment link above.

Java Web Start Deployment

For a synopsis of Java Web Start deployment features and enhancements, click the above link.

Tools and Tool Architecture

Java Virtual Machine Tool Interface (JVMTI)

JVMTI is a new native programming interface for use by development and monitoring tools. It provides both a way to inspect the state and to control the execution of applications running in the Java virtual machine (VM). JVMTI is intended to provide a VM interface for the full breadth of tools that need access to VM state, including but not limited to: profiling, debugging, monitoring, thread analysis, and coverage analysis tools.

JVMTI will replace the now deprecated JVMPI and JVMDI in the next major release of J2SE.

Java Platform Debugger Architecture (JPDA)

JPDA itself has many new features, described in more detail on the JPDA enhancements page.
  • A read-only subset of JDI has been defined. This subset can be used on a debuggee in which no debug code can be executed (such as a core file or a process that is hung or was not started in debug mode). The subset allows creation of JDI connectors for use in debugging such debuggees.
  • A service provider interface for connectors and transports allows debugger vendors, or even end users, to create their own JDI connectors and transports and plug them into the JPDA reference implementation. For example, a connector could be provided to use SSL to communicate between the debugger and debuggee.
  • JDI supports the new language features (generics, enums, and varargs).
  • The lowest layer of JPDA, the Java Virtual Machine Debugger Interface (JVMDI), has been deprecated and will be removed in the next major J2SE release. Replacing it is the Java Virtual Machine Tool Interface (JVMTI). This is a more general interface that allows profiling to be done as well as debugging. The current profiling interface, Java Virtual Machine Profiling Interface(JVMPI) is also deprecated and will be removed in the next major release.
  • The JPDA reference implementation includes new JDI connectors that allow corefiles and hung processes to be debugged.

Java Compiler (javac)

Compiler options include:
  • -source 1.5 - Enable 1.5 specific language features to be used in source files. (-target 1.5 is implied.)
  • -target 1.5 - Allow javac to use 1.5 specific features in the libraries and virtual machine.
  • -Xlint - Enable javac to produce warning messages about legal, but suspect and often problematic, program constructs. An example would be declaring a class that implements Serializable but does not define a serialVersionUID.
  • -d32 - Indicate a 32-bit Solaris or Linux platform.
  • -d64 - Indicate a 64-bit Solaris or Linux platform.
  • -target cldc1.0 - Generate class files suitable for use on VMs in Connected Limited Device Configuration (CLDC) version 1.0 and later. The compiler generates stack maps making the use of the preverifier unnecessary.

New Programmatic Interface

The com.sun.tools.javac.Main class provides two static methods to invoke the compiler from a program. See the man page for details.

Javadoc Tool

See What's New in Javadoc 5.0

Annotation Processing Tool (apt)

apt is a new command-line utility for annotation processing. It includes a set of reflective APIs and supporting infrastructure to process program annotations.

Java TM 2 Platform, Standard Edition 5.0 Trouble-Shooting and Diagnostic Guide

This guide provides descriptions of tools, options, and other items for use in analyzing problems. It contains suggestions about what to try before submitting a bug report and what data to collect for a report.

OS & Hardware Platforms

Supported System Configurations

For more information, click the above link.

64-Bit AMD Opteron Processors

With J2SE 5, AMD Opteron processors are supported by the server VM on Suse Linux and on Windows 2003

Primitive Data Types

The Java programming language is strongly-typed, which means that all variables must first be declared before they can be used. This involves stating the variable's type and name, as you've already seen:

int gear = 1;
Doing so tells your program that a field named "gear" exists, holds numerical data, and has an initial value of "1". A variable's data type determines the values it may contain, plus the operations that may be performed on it. In addition to int, the Java programming language supports seven other primitive data types. A primitive type is predefined by the language and is named by a reserved keyword. Primitive values do not share state with other primitive values. The eight primitive data types supported by the Java programming language are:
  • byte: The byte data type is an 8-bit signed two's complement integer. It has a minimum value of -128 and a maximum value of 127 (inclusive). The byte data type can be useful for saving memory in large arrays, where the memory savings actually matters. They can also be used in place of int where their limits help to clarify your code; the fact that a variable's range is limited can serve as a form of documentation.
  • short: The short data type is a 16-bit signed two's complement integer. It has a minimum value of -32,768 and a maximum value of 32,767 (inclusive). As with byte, the same guidelines apply: you can use a short to save memory in large arrays, in situations where the memory savings actually matters.
  • int: The int data type is a 32-bit signed two's complement integer. It has a minimum value of -2,147,483,648 and a maximum value of 2,147,483,647 (inclusive). For integral values, this data type is generally the default choice unless there is a reason (like the above) to choose something else. This data type will most likely be large enough for the numbers your program will use, but if you need a wider range of values, use long instead.
  • long: The long data type is a 64-bit signed two's complement integer. It has a minimum value of -9,223,372,036,854,775,808 and a maximum value of 9,223,372,036,854,775,807 (inclusive). Use this data type when you need a range of values wider than those provided by int.
  • float: The float data type is a single-precision 32-bit IEEE 754 floating point. Its range of values is beyond the scope of this discussion, but is specified in section 4.2.3 of the Java Language Specification. As with the recommendations for byte and short, use a float (instead of double) if you need to save memory in large arrays of floating point numbers. This data type should never be used for precise values, such as currency. For that, you will need to use the java.math.BigDecimal class instead. Numbers and Strings covers BigDecimal and other useful classes provided by the Java platform.
  • double: The double data type is a double-precision 64-bit IEEE 754 floating point. Its range of values is beyond the scope of this discussion, but is specified in section 4.2.3 of the Java Language Specification. For decimal values, this data type is generally the default choice. As mentioned above, this data type should never be used for precise values, such as currency.
  • boolean: The boolean data type has only two possible values: true and false. Use this data type for simple flags that track true/false conditions. This data type represents one bit of information, but its "size" isn't something that's precisely defined.
  • char: The char data type is a single 16-bit Unicode character. It has a minimum value of '\u0000' (or 0) and a maximum value of '\uffff' (or 65,535 inclusive).
In addition to the eight primitive data types listed above, the Java programming language also provides special support for character strings via the java.lang.String class. Enclosing your character string within double quotes will automatically create a new String object; for example, String s = "this is a string";. String objects are immutable, which means that once created, their values cannot be changed. The String class is not technically a primitive data type, but considering the special support given to it by the language, you'll probably tend to think of it as such. You'll learn more about the String class in Simple Data Objects

Default Values

It's not always necessary to assign a value when a field is declared. Fields that are declared but not initialized will be set to a reasonable default by the compiler. Generally speaking, this default will be zero or null, depending on the data type. Relying on such default values, however, is generally considered bad programming style.

The following chart summarizes the default values for the above data types.

Data Type Default Value (for fields)
byte 0
short 0
int 0
long 0L
float 0.0f
double 0.0d
char '\u0000'
String (or any object) null
boolean false

Local variables are slightly different; the compiler never assigns a default value to an uninitialized local variable. If you cannot initialize your local variable where it is declared, make sure to assign it a value before you attempt to use it. Accessing an uninitialized local variable will result in a compile-time error.

Literals

You may have noticed that the new keyword isn't used when initializing a variable of a primitive type. Primitive types are special data types built into the language; they are not objects created from a class. A literal is the source code representation of a fixed value; literals are represented directly in your code without requiring computation. As shown below, it's possible to assign a literal to a variable of a primitive type:

     boolean result = true;
char capitalC = 'C';
byte b = 100;
short s = 10000;
int i = 100000;
The integral types (byte, short, int, and long) can be expressed using decimal, octal, or hexadecimal number systems. Decimal is the number system you already use every day; it's based on 10 digits, numbered 0 through 9. The octal number system is base 8, consisting of the digits 0 through 7. The hexadecimal system is base 16, whose digits are the numbers 0 through 9 and the letters A through F. For general-purpose programming, the decimal system is likely to be the only number system you'll ever use. However, if you need octal or hexadecimal, the following example shows the correct syntax. The prefix 0 indicates octal, whereas 0x indicates hexadecimal.

     int decVal = 26;  // The number 26, in decimal
int octVal = 032; // The number 26, in octal
int hexVal = 0x1a; // The number 26, in hexadecimal

The floating point types (float and double) can also be expressed using E or e (for scientific notation), F or f (32-bit float literal) and D or d (64-bit double literal; this is the default and by convention is omitted).

     double d1 = 123.4;
double d2 = 1.234e2; // same value as d1, but in scientific notation
float f1 = 123.4f;

Literals of types char and String may contain any Unicode (UTF-16) characters. If your editor and file system allow it, you can use such characters directly in your code. If not, you can use a "Unicode escape" such as '\u0108' (capital C with circumflex), or "S\u00ED se\u00F1or" (Sí Señor in Spanish). Always use 'single quotes' for char literals and "double quotes" for String literals. Unicode escape sequences may be used elsewhere in a program (such as in field names, for example), not just in char or String literals.

The Java programming language also supports a few special escape sequences for char and String literals: \b (backspace), \t (tab), \n (line feed), \f (form feed), \r (carriage return), \" (double quote), \' (single quote), and \\ (backslash).

There's also a special null literal that can be used as a value for any reference type. null may be assigned to any variable, except variables of primitive types. There's little you can do with a null value beyond testing for its presence. Therefore, null is often used in programs as a marker to indicate that some object is unavailable.

Finally, there's also a special kind of literal called a class literal, formed by taking a type name and appending ".class"; for example, String.class. This refers to the object (of type Class) that represents the type itself.