Manual de Java MANUAL DE JAVA Rodolfo J. Rodríguez-R. [email protected] ÍNDICE: 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. RESUMEN PROGRAMACIÓN CLIENTE-SERVIDOR PLUG-INS SCRIPTS JAVA ACTIVEX SCRIPTLETS JAVA EN "DOS PALABRAS" ORIGEN DE JAVA CARACTERÍSTICAS DE JAVA ORIENTADO A OBJETOS DISTRIBUIDO ROBUSTO SEGURO PORTABLE INTERPRETADO DINÁMICO DIFERENCIAS Y SIMILITUDES CON C++ JAVA PARA APLICACIONES CORPORATIVAS DESARROLLO RÁPIDO DE APLICACIONES APLICACIONES EFECTIVAS Y EFICIENTES PORTABILIDAD PARA PROGRAMADOR Y PROGRAMA COSTOS DE DESARROLLO MANTENIMIENTO Y SOPORTE APRENDIZAJE RESUMEN PRIMEROS PASOS EN JAVA Rodolfo-J. Rodríguez-R. E-mail: [email protected] 2 3 4 4 4 5 5 6 8 9 10 10 10 13 15 15 19 21 24 25 25 26 27 27 29 29 31 Manual de Java 1. Resumen El uso principal que se hace de Internet e incluso de las redes internas (corporativas) es correo electrónico (e-mail), aunque actualmente hay un auge sorprendente de la navegación web. Los documentos web pueden contener variedad de texto, gráficos de todas clases y proporcionar enlaces hipertexto hacia cualquier lugar de la red. Los navegadores utilizan documentos escritos en lenguaje HTML. La combinación actual de navegadores HTML/WWW está limitada pues a texto y gráficos. Si se quiere reproducir un sonido o ejecutar un programa de demostración, primero hemos de bajarnos (download) el fichero en cuestión y luego utilizar un programa en nuestro ordenador capaz de entender el formato de ese fichero, o bien cargar un módulo (plug-in) en nuestro navegador para que pueda interpretar el fichero que hemos bajado. Hasta ahora, la única forma de realizar una página web con contenido interactivo, era mediante la interfaz CGI (Common Gateway Interface), que permite pasar parámetros entre formularios definidos en lenguaje HTML y programas escritos en Perl o en C. Esta interfaz resulta muy incómoda de programar y es pobre en sus posibilidades. El lenguaje Java y los navegadores con soporte Java, proporcionan una forma diferente de hacer que ese navegador sea capaz de ejecutar programas. Con Java se puede reproducir sonido directamente desde el navegador, se pueden visitar home pages con animaciones, se puede enseñar al navegador a manejar nuevos formatos de ficheros, e incluso, cuando se pueda transmitir vídeo por las líneas telefónicas, nuestro navegador estará preparado para mostrar esas imágenes. Utilizando Java, se pueden eliminar los inconvenientes de la interfaz CGI y también se pueden añadir aplicaciones que vayan desde experimentos científicos interactivos de propósito educativo, a juegos o aplicaciones especializadas para la televenta. Es posible implementar publicidad interactiva y periódicos personalizados. Por ejemplo, alguien podría escribir un programa Java que implementara una simulación química interactiva -una cadena de adn-. Utilizando un navegador con soporte Java, un usuario podría recibir fácilmente esa simulación e interaccionar con ella, en lugar de conseguir simplemente un dibujo estático y algo de texto. Lo recibido cobra vida. Además, con Java podemos estar seguros de que el código que hace funcionar el experimento químico no contiene ningún trozo de código malicioso que dañe al sistema. El código que intente actuar destructivamente o que contenga errores, no podrá traspasar los muros defensivos colocados por las características de seguridad y robustez de Java. Además, Java proporciona una nueva forma de acceder a las aplicaciones. El software viaja transparentemente a través de la red. No hay necesidad de instalar las aplicaciones, ellas mismas vienen cuando se necesitan. Por ejemplo, la mayoría de los navegadores del Web pueden procesar un reducido número de formatos gráficos (típicamente GIF y JPEG). Si se encuentran con otro tipo de formato, el navegador estándar no tiene capacidad para procesarlo, tendría que ser actualizado para poder aprovechar las ventajas del nuevo formato. Sin embargo, un navegador con soporte Java puede enlazar con el servidor que contiene el algoritmo que procesa ese nuevo formato y mostrar la imagen. Por lo tanto, si alguien inventa un nuevo algoritmo de compresión para Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java imágenes, el inventor sólo necesita estar seguro de que hay una copia en código Java de ese algoritmo instalada en el servidor que contiene las imágenes que quiere publicar. Es decir, los navegadores con soporte Java se actualizan a sí mismos sobre la marcha, cuando encuentran un nuevo tipo de fichero o algoritmo. En esta filosofía es en la que se basan los NC (Network Computer), que serán ordenadores sin disco y con mucha memoria. Sus programas residen en un servidor que se los envía cuando los solicita. Es quizá un guiño al pasado y una versión futurista de lo que ha sido un Terminal-X en otros tiempos, salvando las diferencias, evidentemente (no sea que alguien me tilde de irreverente con las nuevas tecnologías). 2. Programación Cliente-Servidor Java es un nuevo lenguaje de programación, como tantos otros. Así que uno se pregunta el por qué del revuelo que se ha formado con su aparición. La respuesta no es inmediatamente obvia si se observa el asunto desde el punto de vista de la programación tradicional, porque aunque resuelve algunos de los problemas típicos de este tipo de programación, lo que verdaderamente es importante es que también resuelve los problemas que se generan en Internet, en la Telaraña Mundial, en el World-Wide-Web, en la Web. Internet puede resultar algo misterioso al principio, sobre todo porque se utiliza un vocabulario propio, que hasta que no se domina, uno anda un poco despistado. Pero, en esencia, Internet es un sistema Cliente-Servidor gigante. La idea primaria de un sistema cliente-servidor es que debe haber un sitio donde se centraliza la información, que se desea distribuir bajo demanda a un conjunto de personas o máquinas. La clave de este concepto radica en que si se produce un cambio en la información del sistema central, inmediatamente es propagada a los receptores de la información, a la parte cliente. Luego, el concepto básico es muy simple; el problema se presenta cuando hay solamente un servidor que tiene colgados a muchos clientes, en que el rendimiento general del sistema decrece de forma exponencial al aumento del número de clientes. El funcionamiento de la Web sigue este mismo principio. Inicialmente, se solicita una información a un servidor y éste envía de vuelta un fichero que será interpretado por el navegador (el cliente) que lo formateará para visualizarlo en la máquina cliente. El navegador fue el primer paso adelante en la expansión de Internet, ya que permitía visualizar un mismo fichero en plataformas diferentes sin hacerle cambio alguno; pero su finalidad principal es la visualización de ficheros, no la interactividad con el usuario, ni la posibilidad de ejecutar programas en la parte del usuario, en la parte cliente del sistema. Para proporcionar un poco de interactividad, se dotó al lenguaje HTML de ciertos mecanismos básicos de entrada de datos, como botones, cajas de selección, campos de texto, y algunos otros; pero la carga que incorporaban al sistema caía del todo dentro del lado del servidor, con lo cual, si había muchos clientes colgando, el colapso del servidor era casi seguro. Así que surgieron algunas alternativas a los CGI, para que se pudiese descargar al servidor de tanto trabajo y que el cliente realizase también operaciones. Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java 3. Plug-ins Esto son piezas de código que se incorporan al navegador y le indican que "a partir de ahora dispones de una nueva característica". Hay características que se añaden a los navegadores a través de plug-ins que son muy rápidas y eficientes, pero el problema es que escribir un plug-in no es una tarea trivial ni tampoco es algo que haya que hacer en el proceso de construcción de un Site. Luego los plug-ins son herramientas válidas para programadores muy expertos que permiten incorporar características nuevas al navegador sin necesidad de que el vendedor conceda su permiso. 4. Scripts Un lenguaje script permite embeber código fuente para la programación del lado cliente, directamente en la página HTML, y el plug-in que interpreta ese lenguaje se activará automáticamente cuando se cargue en el navegador. Estos lenguajes tienden a ser muy simples y sencillos, además se cargan muy rápidamente porque van incluidos en la página que envía el servidor. La pega es que el código del programador está expuesto a la vista de cualquiera, aunque tampoco se pueden hacer demasiadas filigranas con un lenguaje script. Estos lenguajes se utilizan fundamentalmente para hacer más atractivos las interfaces gráficas de las páginas, porque disponen de elementos gráficos y pueden llegar a resolver el 80% de los problemas que se plantean en la programación de la parte cliente del sistema cliente-servidor; y, además, son lenguajes mucho más sencillos de aprender e implementar soluciones con ellos que recurrir a Java o ActiveX. Siempre que los problemas de el caigan dentro de ese 80% que son capaces de resolver los lenguajes script, y el programador se encuentre cómodo con este tipo de lenguajes, serían la elección prioritaria, antes de adentrarse en las profundidades que representa siempre el estudio de un nuevo lenguaje de programación. El lenguaje script más utilizado es JavaScript, que no tiene nada que ver con Java, me imagino que se llamará así para aprovechar el tirón de popularidad de Java, pero también se puede realizar scripts en la parte cliente con Visual Basic o con Tcl/Tk. 5. Java ¿Y qué pasa con el 20% de los problemas que no pueden resolver los lenguajes script? La respuesta más común, si se hiciese una encuesta, sería Java, y no solamente porque sea un poderoso lenguaje de programación enfocado a la seguridad, multi-plataforma e internacional, sino porque Java está siendo continuamente extendido para proporcionarle nuevas características y librerías que resuelven elegantemente problemas que son muy difíciles en la programación tradicional como el acceso a bases de datos, el uso de multihilo, la programación de redes y la programación distribuida, y además porque Java, a través de los applets, permite la programación de la parte cliente. Un applet es un miniprograma que corre solamente bajo un navegador y es descargado automáticamente como parte de una página Web, al igual que cualquier gráfico, y cuando se activa, ejecuta un programa. Este es el interés, proporciona una forma a través de la cual se puede distribuir software al cliente desde el servidor, en el momento en que el cliente necesite ese software, y no Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java antes, con lo cual siempre tendrá el cliente la última versión de ese software, se actualice cuando se actualice. Además, tal como está diseñado Java, el programador necesita crear su programa una sola vez, y ya estará listo para ser ejecutado en todas las plataformas que dispongan de un navegador con soporte Java. Con Java se podrá realizar tanto trabajo como sea posible en el cliente antes y después de hacer peticiones al servidor. Por ejemplo, se puede evitar el enviar una petición a través de Internet mientras el usuario no haya introducido los parámetros correctos de esa petición, que estará chequeando el cliente, sin necesidad de tener que consultar continuamente al servidor; con ello se gana en velocidad de respuesta ante el usuario, una reducción general en el tráfico de red y una gran descarga de trabajo para el servidor. Una de las ventajas de los applets sobre los scripts es que están en forma compilada, con lo cual el código fuente no es visible; aunque se puede descompilar sin demasiadas complicaciones, pero vamos, no está del todo accesible. Además, un applet puede comprimir varios módulos, utilizando ficheros JAR, evitando múltiples conexiones con el servidor, ya que en una sola se descargan todos los componentes necesarios. Y, finalmente, está la curva de aprendizaje, porque a pesar de lo que el lector haya podido escuchar o leer por ahí, Java no es un lenguaje trivial. Si el lector domina Visual Basic, por ejemplo, el que realice sus trabajos en VBscript le resultará más fácil y rápido y resolverá sus problemas de programación clienteservidor sin embarcarse en la dura empresa de aprender Java. 6. ActiveX La competencia directa de Java es ActiveX, de Microsoft, aunque su enfoque sea bastante diferente. ActiveX es originalmente una solución orientada a entornos Windows, aunque parece ser que ahora está siendo desarrollado para ser multi-plataforma. Lo que hace ActiveX es decir "si tu programa se conecta a este entorno, se podrá descargar en una página Web y correr bajo un navegador que soporte controles ActiveX". Microsoft. Internet Explorer soporta ActiveX directamente y Netscape lo soporta a través de plug-in. Por lo tanto, ActiveX no está constreñido a un solo lenguaje de programación, sino que se pueden desarrollar componentes ActiveX en el lenguaje que domine el programador, ya sea C++, Visual Basic o el Delphi de Borland. 7. Scriptlets Microsoft ha subido una vez más la apuesta en su batalla contra Java con el lanzamiento de los scriplets, que son similares en naturaleza a los componentes JavaBeans, y aparecen como una campaña de vaporware por parte de Microsoft. Su aparente meta es posicionar esta tecnología como un potencial rival multi-platafroma de Java, que, según dice Microsoft, no cumple su compromiso de ser tan manejable como propugna su publicidad. Los scriplets, a diferencia de Java, sólo se pueden utilizar sobre un navegador Web. Si bien es cierto que a los applets les ocurre lo mismo, Java deja abierta la posibilidad de crear aplicaciones, dependientes de una máquina virtual Java, pero no de un navegador; y en cuanto la máquina virtual Java se encuentra incluida en el propio sistema operativo, el usuario no advierte dependencia Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java alguna. La verdad es que los scriplets no aportan nada nuevo a las posibilidades de las herramientas actuales, sino que son otra forma de hacer lo mismo. La descarga y ejecución automática de programas a través de Internet, en principio, suena como el sueño de cualquier creador de virus. Los componentes ActiveX son especialmente sensibles a este ataque, ya que se puede hacer lo que se quiera, sin control alguno, con lo cual, el usuario puede bajarse un componente ActiveX que haga estragos en su máquina. Esto no es nuevo, sino que es un problema largamente conocido desde los tiempos de las BBS, pero que aquí se ve amplificado por la velocidad de Internet. Cuando se pide una página Web, se reciben ficheros gráficos, el código de la página (con o sin scripts), código Java precompilado y componentes ActiveX. De estos, algunos son casi inofensivos, como los ficheros gráficos y el código HTML de la página, porque es muy poco lo que se puede manipular sobre ellos. Java está diseñado para ejecutar los applets en una caja cerrada (sand box), envuelta en una capa de seguridad que impide cualquier acceso a disco o a memoria que se encuentre fuera de esa caja cerrada. Así que, la parte más propensa a introducir elementos no deseados en la máquina cliente son los componentes ActiveX. Actualmente se está intentando paliar esta desagradable posibilidad a través de las firmas digitales, que permiten reconocer al autor. Esta idea parte de que los autores de virus normalmente son anónimos, y si se eliminan estos componentes anónimos, siempre se podrá forzar al programador a que sea responsable de sus acciones. Puede ser una buena idea, porque permitirá a los programas ser más funcionales, aunque si un programa tiene un bug inadvertido que pueda resultar destructivo, todavía podrá causar problemas. Con respecto a Java, hay diversas opiniones respecto a la draconiana restricción a que un applet no pueda escribir en el disco local del cliente; porque, que pasa si el usuario quiere crear una base de datos local, o quiere guardar cualquier tipo de información para cuando se encuentre desconectado de Internet. La asunción inicial de que todo el mundo estaría conectado es impracticable, aunque si se redujesen los precios del teléfono, pudiese llegar a ser el estado normal de muchos usuarios; así que la solución debe llegar por otra vía. Los applets firmados, que utilizan una clave pública para comprobar que el applet viene del lugar correcto y no ha sido manipulado puede ser una de esas soluciones. Desde Java 1.1 se dispone de un entorno para implementar firmas digitales, por lo que sí fuese necesario se podría hacer que un applet se saliese de su caja cerrada. 8. Java en "dos palabras" A continuación se explica de forma muy resumida y básica cómo funciona Java, extendiendo las pinceladas que se han soltado en secciones anteriores, porque es importante conocer el funcionamiento del lenguaje para saber cuáles son sus virtudes y cuáles sus defectos. Esto son cosas muy básicas sobre Java, por lo que va dirigido a aquellos lectores que no posean conocimientos algo avanzados. Java es el primer lenguaje que tiene la virtud de ser compilado e interpretado de forma simultánea. Cuando un programador realiza una aplicación o un applet en Java y lo compila, en realidad, el compilador no trabaja como un Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java compilador de un lenguaje al uso. El compilador Java únicamente genera el denominado ByteCode. Este código es un código intermedio entre el lenguaje máquina del procesador y Java. Evidentemente este código no es ejecutable por sí mismo en ninguna plataforma hardware, pues no se corresponde con el lenguaje de ninguno de los procesadores que actualmente se conocen (habrá que esperar a ver qué ocurre con los procesadores Java). Por lo tanto, para ejecutar una aplicación Java es necesario disponer de un mecanismo que permita ejecutar el ByteCode. Este mecanismo es la denominada Máquina Virtual Java. En cada plataforma (Unix, Linux, Windows 95/NT, Macintosh, etc.) existe una máquina virtual específica. Así que cuando el ByteCode llega a la máquina virtual, ésta lo interpreta pasándolo a código máquina del procesador donde se esté trabajando, y ejecutando las instrucciones en lenguaje máquina que se deriven de la aplicación Java. De este modo, cuando el mismo ByteCode llega a diferentes plataformas, éste se ejecutará de forma correcta, pues en cada una de esas plataformas existirá la máquina virtual adecuada. Con este mecanismo se consigue la famosa multi-plataforma de Java, que con sólo codificar una vez, podemos ejecutar en varias plataformas. En realidad la máquina virtual desempeña otras funciones, como la de aislar los programas Java al entorno de la máquina virtual, consiguiendo una gran seguridad. Sin embargo, como podrá estar deduciendo el lector, esto tiene algunas desventajas, y la más clara es la velocidad de ejecución. Puesto que la máquina virtual debe estar interpretando constantemente el ByteCode, se consume demasiado tiempo de procesador en realizar esta interpretación, que por otra parte no aporta nada a la aplicación, obteniendo así un bajo rendimiento. Para solucionarlo se han adoptado soluciones intermedias. Una de las más novedosas y útiles son los compiladores JIT (Just-In-Time). Estos compiladores están situados a la entrada de la máquina virtual, de forma que según llega el ByteCode lo van compilando al lenguaje máquina del procesador. A diferencia de la interpretación, el compilador no ejecuta el ByteCode, únicamente lo traduce y lo almacena en código nativo dentro de la máquina virtual. Así, una vez que la aplicación está dentro de la máquina virtual, ya se encuentra en lenguaje máquina y, por lo tanto, será directamente ejecutable, sin necesidad de interpretaciones, consiguiendo dotar de mayores rendimientos a la aplicación. Que Java es lento, resultará pues evidente, pero vamos, hasta los más pesimistas respecto a Java, como Microsoft, reconocen que Java obtendrá gracias a los compiladores JIT un rendimiento cercano al 80% del de C++, lo cual es más que suficiente para la mayoría de las aplicaciones; y más aún si se tiene en cuenta el sector al cual va dirigido Java, porque, al fin y al cabo, tampoco se trata de escribir el Doom III en Java. No obstante, el uso de ByteCode no es la única causa de que Java sea más lento que C++. Porque este último lenguaje no tiene un recolector de basura, ni que cargar clases dinámicamente, ni realizar comprobaciones en tiempo de ejecución como la de los límites de los arrays, las condiciones de seguridad o que el ByteCode no esté manipulado para acceder ilegalmente a campos marcados como privados o protegidos. Estas características suponen una sobrecarga importante, sólo el recolector de basura puede superar el 15%, y son la causa última de que Java no pueda alcanzar el cien por cien del rendimiento de C++. A pesar de todo, hay grandes expectativas en la compilación dinámica y en la propia mejora de los elementos que integran la máquina virtual como el recolector de basura, Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java porque afortunadamente, a diferencia de otras ocasiones, muchas empresas e investigadores no se han quedado en una queja estéril y se han puesto a trabajar para solucionar estas cuestiones. A cambio de este incremento de la carga se obtiene mayor fiabilidad, lo que reduce ostensiblemente el coste de mantenimiento y un sinfín de nuevas posibilidades. Muy breve y de forma muy genérica, este es el funcionamiento básico de Java. Todas las mejoras al lenguaje se centran básicamente en conseguir mejores tiempos de ejecución y dotar de mayores prestaciones a la máquina virtual. 9. Origen de Java Sun Microsystems, líder en servidores para Internet, uno de cuyos lemas desde hace mucho tiempo ha sido "the network is the computer" (lo que quiere dar a entender que el verdadero ordenador es la red en su conjunto y no cada máquina individual), es quien ha inventado el lenguaje Java, en un intento de resolver simultáneamente todos los problemas que se planteaban a los desarrolladores de software por la proliferación de arquitecturas incompatibles, tanto entre las diferentes máquinas como entre los diversos sistemas operativos y sistemas de ventanas que funcionan sobre una misma máquina, añadiendo la dificultad de crear aplicaciones distribuidas en una red como Internet. He podido leer más de cinco versiones distintas sobre el origen, concepción y desarrollo de Java, desde la que dice que este fue un proyecto que rebotó durante mucho tiempo por distintos departamentos de Sun sin que nadie le prestara ninguna atención, hasta que finalmente encontró su nicho de mercado en la aldea global que es Internet; hasta la más difundida, que justifica a Java como lenguaje de pequeños electrodomésticos. Hace algunos años, Sun Microsystems decidió intentar introducirse en el mercado de la electrónica de consumo y desarrollar programas para pequeños dispositivos electrónicos. Tras unos comienzos dudosos, Sun decidió crear una filial, denominada FirstPerson Inc., para dar margen de maniobra al equipo responsable del proyecto. El mercado inicialmente previsto para los programas de FirstPerson eran los equipos domésticos: microondas, tostadoras y, fundamentalmente, televisión interactiva. Este mercado, dada la falta de sofisticación de los usuarios, requerían de interfaces mucho más cómodos e intuitivos que los sistemas de ventanas que proliferaban en el momento. Otros requisitos importantes eran la fiabilidad del código y la facilidad de desarrollo. James Gosling, el miembro del equipo con más experiencia en lenguajes de programación, decidió que las ventajas de eficiencia de C++ no compensaban el gran coste de pruebas y depuración. Gosling había estado trabajando en su tiempo libre en un lenguaje de programación que él había llamado Oak, según parece el nombre se debe al roble que se veía por la ventana de su casa (¡originalidad ante todo!), el cual, aún partiendo de la sintaxis de C++, intentaba remediar las deficiencias que había observado. Los lenguajes al uso, como C o C++, deben ser compilados para un chip, y si se cambia el chip, todo el software debe compilarse de nuevo. Esto encarece mucho los desarrollos y el problema es especialmente acusado en el campo de la electrónica de consumo. La aparición de un chip más barato y, generalmente, más eficiente, conduce inmediatamente a los fabricantes a incluirlo en las nuevas series de sus cadenas de producción, por pequeña que Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java sea la diferencia en precio ya que, multiplicada por la tirada masiva de los aparatos, supone un ahorro considerable. Por tanto, Gosling decidió mejorar las características de Oak y utilizarlo. El primer proyecto en que se aplicó este lenguaje recibió el nombre de proyecto Green y consistía en un sistema de control completo de los aparatos electrónicos y el entorno de un hogar. Para ello se construyó un ordenador experimental denominado *7 (Star Seven). El sistema presentaba una interfaz basada en la representación de la casa de forma animada y el control se llevaba a cabo mediante una pantalla sensible al tacto. En el sistema aparecía Duke, la actual mascota de Java. Posteriormente se aplicó a otro proyecto denominado VOD (Video On Demand) en el que se empleaba como interfaz para la televisión interactiva. Ninguno de estos proyectos se convirtió nunca en un sistema comercial, pero fueron desarrollados enteramente en un Java primitivo y fueron como su bautismo de fuego. Una vez que en Sun se dieron cuenta de que a corto plazo la televisión interactiva no iba a ser un gran éxito, urgieron a FirstPerson a desarrollar con rapidez nuevas estrategias que produjeran beneficios. No lo consiguieron y FirstPerson cerró en la primavera de 1994. Pese a lo que parecía ya un olvido definitivo, Bill Joy, cofundador de Sun y uno de los desarrolladores principales del Unix de Berkeley, juzgó que Internet podría llegar a ser el campo de juego adecuado para disputar a Microsoft su primacía casi absoluta en el terreno del software, y vio en Oak el instrumento idóneo para llevar a cabo estos planes. Tras un cambio de nombre y algunos de diseño, el lenguaje Java fue presentado en sociedad en agosto de 1995. Lo mejor será hacer caso omiso de las historias que pretenden dar carta de naturaleza a la clarividencia industrial de sus protagonistas; porque la cuestión es si independientemente de su origen y entorno comercial, Java ofrece soluciones a nuestras expectativas. Porque tampoco vamos a desechar la penicilina aunque haya sido su origen fruto de la casualidad. 10. Características de Java Las características principales que nos ofrece Java respecto a cualquier otro lenguaje de programación, serían: Simple Java ofrece toda la funcionalidad de un lenguaje potente, pero sin las características menos usadas y más confusas de éstos. C++ no es un lenguaje conveniente por razones de seguridad, pero C y C++ son los lenguajes más difundidos, por ello Java se diseñó para ser parecido a C++ y así facilitar un rápido y fácil aprendizaje. Java elimina muchas de las características de otros lenguajes como C++, para mantener reducidas las especificaciones del lenguaje y añadir características muy útiles como el garbage collector (reciclador de memoria dinámica). No es necesario preocuparse de liberar memoria, el reciclador se encarga de ello y como es de baja prioridad, cuando entra en acción, permite liberar bloques de memoria muy grandes, lo que limita en mucho la fragmentación de la memoria. Java reduce en un 50% los errores más comunes de programación con lenguajes como C y C++ al eliminar muchas de las características de éstos, entre las que destacan: • aritmética de punteros • no existen referencias Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java registros (struct) definición de tipos (typedef) macros (#define) necesidad de liberar memoria (free) Aunque, en realidad, lo que hace es eliminar las palabras reservadas (struct, typedef), ya que las clases son algo parecido. Además, el intérprete completo de Java que hay en este momento es muy pequeño, solamente ocupa 215 Kb de RAM. • • • • 11. Orientado a Objetos Java implementa la tecnología básica de C++ con algunas mejoras y elimina algunas cosas para mantener el objetivo de la simplicidad del lenguaje. Java trabaja con sus datos como objetos y con interfaces a esos objetos. Soporta las tres características propias del paradigma de la orientación a objetos: encapsulación, herencia y polimorfismo. Las plantillas de objetos son llamadas, como en C++, clases y sus copias, instancias. Estas instancias, como en C++, necesitan ser construidas y destruidas en espacios de memoria. Java incorpora funcionalidades inexistentes en C++ como por ejemplo, la resolución dinámica de métodos. Esta característica deriva del lenguaje Objective C, propietario del sistema operativo Next. En C++ se suele trabajar con librerías dinámicas (DLLs) que obligan a recompilar la aplicación cuando se retocan las funciones de su interior. Este inconveniente es resuelto por Java mediante una interfaz específica llamada RTTI (RunTime Type Identification) que define la interacción entre objetos excluyendo variables de instancias o implementación de métodos. Las clases en Java tienen una representación en el runtime que permite a los programadores interrogar por el tipo de clase y enlazar dinámicamente la clase con el resultado de la búsqueda. 12. Distribuido Java se ha construido con extensas capacidades de interconexión TCP/IP. Existen librerías de rutinas para acceder e interactuar con protocolos como http y ftp. Esto permite a los programadores acceder a la información a través de la red con tanta facilidad como a los ficheros locales. Java en sí no es distribuido, sino que proporciona las librerías y herramientas para que los programas puedan ser distribuidos, es decir, que se corran en varias máquinas, interactuando. 13. Robusto Java realiza verificaciones en busca de problemas tanto en tiempo de compilación como en tiempo de ejecución. La comprobación de tipos en Java ayuda a detectar errores, lo antes posible, en el ciclo de desarrollo. Java obliga a la declaración explícita de métodos, reduciendo así las posibilidades de error. Maneja la memoria para eliminar las preocupaciones por parte del programador de la liberación o corrupción de memoria. Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java También implementa los arrays auténticos, en vez de listas enlazadas de punteros, con comprobación de límites, para evitar la posibilidad de sobreescribir o corromper memoria resultado de punteros que señalan a zonas equivocadas. Estas características reducen drásticamente el tiempo empleado en el desarrollo de aplicaciones Java. Además, para asegurar el funcionamiento de la aplicación, realiza una verificación de los ByteCodes, que son el resultado de la compilación de un programa Java. Es un código de máquina virtual que es interpretado por el intérprete Java. No es el código máquina directamente entendible por el hardware, pero ya ha pasado todas las fases del compilador: análisis de instrucciones, orden de operadores, etc., y ya tiene generada la pila de ejecución de órdenes. Java proporciona, pues: • Comprobación de punteros • Comprobación de límites de arrays • Excepciones • Verificación de ByteCodes • Arquitectura Neutral Para establecer Java como parte integral de la red, el compilador Java compila su código a un fichero objeto de formato independiente de la arquitectura de la máquina en que se ejecutará. Cualquier máquina que tenga el sistema de ejecución (run-time) puede ejecutar ese código objeto, sin importar en modo alguno la máquina en que ha sido generado. Actualmente existen sistemas runtime para Solaris 2.x, SunOs 4.1.x, Windows '95, Windows NT, Linux, Irix, Aix, Mac, Apple y probablemente haya grupos de desarrollo trabajando en el porting a otras plataformas. El código fuente Java se "compila" a un código de bytes de alto nivel independiente de la máquina. Este código (ByteCode) está diseñado para ejecutarse en una máquina hipotética que es implementada por un sistema runtime, que sí es dependiente de la máquina. En una representación en que tuviésemos que indicar todos los elementos que forman parte de la arquitectura de Java sobre una plataforma genérica, obtendríamos una imagen como la siguiente: Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java En ella podemos ver que lo verdaderamente dependiente del sistema es la Máquina Virtual Java (JVM) y las librerías fundamentales, que también permitirían acceder directamente al hardware de la máquina. Además, siempre habrá APIs de Java que también entren en contacto directo con el hardware y serán dependientes de la máquina, como ejemplo de este tipo de APIs podemos citar: • Swing : Mejora de las herramientas para la implementación de interfaces de usuario • Java 2d: gráficos 2D y manipulación de imágenes • Java Media Framework: Elementos críticos en el tiempo: audio, vídeo... • Java Animation: Animación de objetos en 2D • Java Telephony: Integración con telefonía • Java Share: Interacción entre aplicaciones multiusuario • Java 3d: Gráficos 3D y su manipulación La siguiente figura ilustra la situación en que se encuentra Java cuando se ejecuta sobre un sistema operativo convencional. En la imagen se observa que si se exceptúa la parte correspondiente al Sistema Operativo que ataca directamente al hardware de la plataforma, el resto está totalmente programado por Javasoft o por los programadores Java, teniendo en cuenta que HotJava es una aplicación en toda regla, al tratarse de un navegador y estar desarrollado en su totalidad en Java. Cualquier programador podría utilizar las mismas herramientas para levantar un nuevo desarrollo en Java, bien fuesen applets para su implantación en Internet o aplicaciones para su uso individual. Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java Y la imagen que aparece a continuación muestra la arquitectura de Java sin un Sistema Operativo que lo ampare, de tal forma que el kernel tendría que proporcionar suficientes posibilidades como para implementar una Máquina Virtual Java y los drivers de dispositivos imprescindibles como pantalla, red, ratón, teclado y la base para poder desarrollar en Java librerías como AWT, ficheros, red, etc. Con todo ello estaría asegurado el soporte completo del API de Java, quedando en mano de los desarrolladores la implementación de aplicaciones o applets o cualquier otra librería. 14. Seguro La seguridad en Java tiene dos facetas. En el lenguaje, características como los punteros o el casting implícito que hace el compilador de C y C++ se eliminan para prevenir el acceso ilegal a la memoria. Cuando se usa Java para crear un navegador, se combinan las características del lenguaje con protecciones de sentido común aplicadas al propio navegador. El lenguaje C, por ejemplo, tiene lagunas de seguridad importantes, como son los errores de alineación. Los programadores de C utilizan punteros en conjunción con operaciones aritméticas. Esto le permite al programador que un puntero referencie a un lugar conocido de la memoria y pueda sumar (o restar) algún valor, para referirse a otro lugar de la memoria. Si otros programadores conocen nuestras estructuras de datos pueden extraer información confidencial de nuestro sistema. Con un lenguaje como C, se pueden tomar números enteros aleatorios y convertirlos en punteros para luego acceder a la memoria: printf( "Escribe un valor entero: " ); scanf( "%u",&puntero ); printf( "Cadena de memoria: %s\n",puntero ); Otra laguna de seguridad u otro tipo de ataque, es el Caballo de Troya. Se presenta un programa como una utilidad, resultando tener una funcionalidad destructiva. Por ejemplo, en UNIX se visualiza el contenido de un directorio con el comando ls. Si un programador deja un comando destructivo bajo esta referencia, se puede correr el riesgo de ejecutar código malicioso, aunque el comando siga haciendo la funcionalidad que se le supone, después de lanzar su carga destructiva. Por ejemplo, después de que el caballo de Troya haya enviado por correo el /etc/shadow a su creador, ejecuta la funcionalidad de ls Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java presentando el contenido del directorio. Se notará un retardo, pero nada inusual. El código Java pasa muchos tests antes de ejecutarse en una máquina. El código se pasa a través de un verificador de ByteCode que comprueba el formato de los fragmentos de código y aplica un probador de teoremas para detectar fragmentos de código ilegal -código que falsea punteros, viola derechos de acceso sobre objetos o intenta cambiar el tipo o clase de un objeto-. Si los ByteCodes pasan la verificación si generar ningún mensaje de error, entonces sabemos que: • El código no produce desbordamiento de operandos en la pila • El tipo de los parámetros de todos los códigos de operación son conocidos y correctos • No ha ocurrido ninguna conversión ilegal de datos, tal como convertir enteros en punteros • El acceso a los campos de un objeto se sabe que es legal: public, private, protected • No hay ningún intento de violar las reglas de acceso y seguridad establecidas El Cargador de Clases también ayuda a Java a mantener su seguridad, separando el espacio de nombres del sistema de ficheros local del de los recursos procedentes de la red. Esto limita cualquier aplicación del tipo Caballo de Troya, ya que las clases se buscan primero entre las locales y luego entre las procedentes del exterior. Las clases importadas de la red se almacenan en un espacio de nombres privado, asociado con el origen. Cuando una clase del espacio de nombres privado accede a otra clase, primero se busca en las clases predefinidas (del sistema local) y luego en el espacio de nombres de la clase que hace la referencia. Esto imposibilita que una clase suplante a una predefinida. En resumen, las aplicaciones de Java resultan extremadamente seguras, ya que no acceden a zonas delicadas de memoria o de sistema, con lo cual evitan la interacción de ciertos virus. Java no posee una semántica específica para modificar la pila de programa o la memoria libre o utilizar objetos y métodos de un programa sin los privilegios del kernel del sistema operativo. Además, para evitar modificaciones por parte de los crackers de la red, implementa un método ultraseguro de autentificación por clave pública. El Cargador de Clases puede verificar una firma digital antes de realizar una instancia de un objeto. Por tanto ningún objeto se crea y almacena en memoria, sin que se validen los privilegios de acceso. Es decir, la seguridad se integra en el momento en que se interpreta, con el nivel de detalle y de privilegio que sea necesario. Con código compilado no sería posible establecer estos niveles de seguridad entre dos objetos pertenecientes al mismo proceso, porque al compartir un único espacio de direcciones, el código de uno podría acceder tranquilamente a cualquier dirección del otro. Dada, pues la concepción del lenguaje y si todos los elementos se mantienen dentro del estándar marcado por Sun, no hay peligro. Java imposibilita, también, abrir ningún fichero de la máquina local (siempre que se realizan operaciones con archivos, éstas trabajan sobre el disco duro de la máquina de donde partió el applet), no permite ejecutar ninguna aplicación nativa de una plataforma e impide que se utilicen otros ordenadores como puente, es decir, Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java nadie puede utilizar nuestra máquina para hacer peticiones o realizar operaciones con otra. Además, los intérpretes que incorporan los navegadores de la Web son aún más restrictivos. Bajo estas condiciones (y dentro de la filosofía de que el único ordenador seguro es el que está apagado, desenchufado, dentro de una cámara acorazada en un bunker y rodeado por mil soldados de los cuerpos especiales del ejército), se puede considerar que Java es un lenguaje seguro y que los applets están libres de virus. Respecto a la seguridad del código fuente, no ya del lenguaje, el propio JDK proporciona un desensamblador de ByteCode, lo cual hace que cualquier programa pueda ser convertido a código fuente, lo que para el programador significa una vulnerabilidad total a su código. Utilizando java no se obtiene el código fuente original, pero sí desmonta el programa mostrando el algoritmo que se utiliza, que es lo realmente interesante. La protección de los programadores ante esto es utilizar llamadas a programas nativos, externos (incluso en C o C++) de forma que no sea descompilable todo el código; aunque así se pierda portabilidad. Es otra de las cuestiones que Java tiene pendientes. 15. Portable Más allá de la portabilidad básica por ser de arquitectura independiente, Java implementa otros estándares de portabilidad para facilitar el desarrollo. Los enteros son siempre enteros y además, enteros de 32 bits en complemento a 2. Además, Java construye sus interfaces de usuario a través de un sistema abstracto de ventanas de forma que las ventanas puedan ser implantadas en entornos Unix, Pc o Mac. 16. Interpretado El intérprete Java (sistema run-time) puede ejecutar directamente el código objeto. Enlazar (linkar) un programa normalmente consume menos recursos que compilarlo, por lo que los desarrolladores con Java pasarán más tiempo desarrollando y menos esperando por el ordenador. No obstante, el compilador actual del JDK es bastante lento. Por ahora, que todavía no hay compiladores específicos de Java para las diversas plataformas, Java es más lento que otros lenguajes de programación, como C++, ya que debe ser interpretado y no ejecutado como sucede en cualquier programa tradicional. Se dice que Java es de 10 a 30 veces más lento que C, y que tampoco existen en Java proyectos de gran envergadura como en otros lenguajes. La verdad es que ya hay comparaciones ventajosas entre Java y el resto de los lenguajes de programación, y una ingente cantidad de folletos electrónicos que supuran fanatismo en favor y en contra de los distintos lenguajes contendientes con Java. Lo que se suele dejar de lado en todo esto, es que primero habría que decidir hasta que punto Java, un lenguaje en pleno desarrollo y todavía sin definición definitiva, está maduro como lenguaje de programación para ser comparado con otros; como por ejemplo con Smalltalk, que lleva más de 20 años en cancha. La verdad es que Java para conseguir ser un lenguaje independiente del sistema operativo y del procesador que incorpore la máquina utilizada, es tanto interpretado como compilado. Y esto no es ningún contrasentido, me explico, el código fuente escrito con cualquier editor se compila generando el ByteCode. Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java Este código intermedio es de muy bajo nivel, pero sin alcanzar las instrucciones máquina propias de cada plataforma y no tiene nada que ver con el p-code de Visual Basic. El ByteCode corresponde al 80% de las instrucciones de la aplicación. Ese mismo código es el que se puede ejecutar sobre cualquier plataforma. Para ello hace falta el runtime, que sí es completamente dependiente de la máquina y del sistema operativo que interpreta dinámicamente el ByteCode y añade el 20% de instrucciones que faltaban para su ejecución. Con este sistema es fácil crear aplicaciones multi-plataforma, pero para ejecutarlas es necesario que exista el runtime correspondiente al sistema operativo utilizado. No obstante, este panorama está cambiando a pasos agigantados, y aunque Java sigue siendo básicamente un lenguaje interpretado, la situación se acerca mucho a la de los programas compilados, sobre todo en lo que a la rapidez en la ejecución del código se refiere. Para comprender el funcionamiento de HotSpot, que es el último lanzamiento que hace Sun y que promete interpretar los ByteCodes más rápido que un programa compilado, las siguientes imágenes muestran cómo actúa el sistema runtime en los diversos casos que hasta ahora pueden darse. Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java La imagen de la izquierda muestra las acciones correspondientes a un compilador tradicional. El compilador traslada las sentencias escritas en lenguaje de alto-nivel a múltiples instrucciones, que luego son enlazadas junto con el resultado de múltiples compilaciones previas que han dado origen a librerías, y juntando todo ello, es cuando genera un programa ejecutable. La imagen de arriba muestra la forma de actuación de un intérprete. Básicamente es un enorme bucle, en el cual se va leyendo o recogiendo cada una de las instrucciones del programa fuente que se desea ejecutar, se analiza, se parte en trozos y se ejecuta. Luego se va a recoger la siguiente instrucción que se debe interpretar y se continúa con este proceso hasta que se terminan las instrucciones o hasta que entre las instrucciones hay alguna que contiene la orden de detener la ejecución de las instrucciones que componen el programa fuente. La imagen siguiente, muestra un tipo de intérprete más eficiente que el anterior, el intérprete de ByteCodes, que fue popularizado hace más de veinte años por la Universidad de California al crear el UCSD Pascal. En este caso, el intérprete trabaja sobre instrucciones que ya han sido trasladadas a un código intermedio en un paso anterior. Así, aunque se ejecute en un bucle, se elimina la necesidad de analizar cada una de las instrucciones que componen el programa fuente, porque ya lo han sido en el paso previo. Este es el sistema que Java utiliza, y la Máquina Virtual Java es un ejemplo de este tipo de intérprete. No obstante, sigue siendo lento, aunque se obtenga un código independiente de plataforma muy compacto, que puede ser ejecutado en Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java cualquier ordenador que disponga de una máquina virtual capaz de interpretar los ByteCodes trasladados. Un paso adelante en el rendimiento del código Java lo han representado los compiladores Just-In-Time, que compilan el código convirtiéndolo a código máquina antes de ejecutarlo. Es decir, un compilador JIT va trasladando los ByteCodes al código máquina de la plataforma según los va leyendo, realizando un cierto grado de optimización. El resultado es que cuando el programa se ejecute, habrá partes que no se ejecuten y que no serán compiladas, y el compilador JIT no perderá el tiempo en optimizar código que nunca se va a ejecutar. No obstante, los compiladores JIT no pueden realizar demasiadas optimizaciones, ya que hay código que ellos no ven, así que aunque siempre son capaces de optimizar la parte de código de inicialización de un programa, hay otras partes que deben ser optimizadas, según se van cargando, con lo cual, hay una cierta cantidad de tiempo que inevitablemente ha de perderse. Y, finalmente, se presenta la última tendencia en lo que a compilación e intérpretes se refiere. Lo último en que trabaja Sun es HotSpot, una herramienta que incluye un compilador dinámico y una máquina virtual para interpretar los ByteCodes, tal como se muestra en la figura siguiente, situada a la izquierda de la página. Cuando se cargan los ByteCodes producidos por el compilador por primera vez, éstos son interpretados en la máquina virtual. Cuando ya están en ejecución, el profiler mantiene información sobre el rendimiento y selecciona el método sobre el que se va a realizar la compilación. Los métodos ya compilados se almacenan en un caché en código máquina nativo. Cuando un método es invocado, esta versión en código máquina nativo es la que se utiliza, en caso de que exista; En caso contrario, los ByteCodes son reinterpretados. La función control que muestra el diagrama es como un salto indirecto a través de la memoria que apunta tanto al código máquina como al interpretado, aunque Sun no ha proporcionado muchos detalles sobre este extremo. Al ser Multihilo (o multihilvanado, mala traducción de multithreaded), Java permite muchas actividades simultáneas en un programa. Los hilos -a veces llamados, procesos ligeros, o hilos de ejecución- son básicamente pequeños procesos o piezas independientes de un gran proceso. Al estar estos hilos construidos en el mismo lenguaje, son más fáciles de usar y más robustos que sus homólogos en C o C++. Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java El beneficio de ser multihilo consiste en un mejor rendimiento interactivo y mejor comportamiento en tiempo real. Aunque el comportamiento en tiempo real está limitado a las capacidades del sistema operativo subyacente (Unix, Windows, etc.) de la plataforma, aún supera a los entornos de flujo único de programa (single-threaded) tanto en facilidad de desarrollo como en rendimiento. Cualquiera que haya utilizado la tecnología de navegación concurrente, sabe lo frustrante que puede ser esperar por una gran imagen que se está trayendo de un sitio interesante desde la red. En Java, las imágenes se pueden ir trayendo en un hilo de ejecución independiente, permitiendo que el usuario pueda acceder a la información de la página sin tener que esperar por el navegador. 17. Dinámico Java se beneficia todo lo posible de la tecnología orientada a objetos. Java no intenta conectar todos los módulos que comprenden una aplicación hasta el mismo tiempo de ejecución. Las librerías nuevas o actualizadas no paralizarán la ejecución de las aplicaciones actuales -siempre que mantengan el API anterior. Java también simplifica el uso de protocolos nuevos o actualizados. Si su sistema ejecuta una aplicación Java sobre la red y encuentra una pieza de la aplicación que no sabe manejar, tal como se ha explicado en párrafos anteriores, Java es capaz de traer automáticamente cualquier pieza que el sistema necesite para funcionar. Java, para evitar que los módulos de ByteCode o los objetos o nuevas clases, no haya que estar trayéndolas de la red cada vez que se necesiten, implementa las opciones de persistencia, para que no se eliminen cuando de limpie la caché de la máquina. Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java Y, para que el lector tenga idea de qué es lo que se mueve alrededor de Java, no hay mejor explicación que la descripción de los APIs que componen la plataforma Java, aunque no todas las que aquí se citan están disponibles para su uso, ya que algunas se encuentran en fase de desarrollo, otras en fase de discusión pública para aporte de ideas y otras en fase beta. Java Enterprise Conjunto de especificaciones para entornos corporativos JDBC API Java Database Connectivity, para permitir a aplicaciones o applets acceder a bases de datos de forma homogénea vía consultas SQL Java RMI Remote Method Invocation, invocación remota de métodos para aplicaciones distribuidas Java IDL Puente de compatibilidad con el modelo estándar de objetos CORBA JNDI Java Naming and Directory Interface, proporciona servicios de directorio y localización de recursos en un entorno corporativo JavaBeans Especificación de componentes basados en Java JAF JavaBeans Activation Framework, entorno para determinar el tipo de datos, encapsular el acceso a ellos, descubrir las acciones que se les pueden aplicar e instanciar el componente JavaBean adecuado Java API Security API para componentes que necesitan encriptación, certificación, firmas digitales y autentificación JFC Java Foundation Classes, jerarquía de clases para el desarrollo de aplicaciones gráficas e interfaces de usuario Swing Set Conjunto de pequeños componentes gráficos para aplicaciones: botones, pestañas, etc. Java 2D Extensión del AWT para el tratamiento de información gráfica bidimensional Java Servlet API Especificación que permite crear applets que se ejecutan en el servidor Java Server API API para el intercambio de información entre un servidor Web y aplicaciones que se ejecutan en su entorno Java Commerce API para transacciones comerciales en Internet API Java Media API Conjunto de especificaciones para el acceso y utilización de información interactiva JMF Java Media Framework, conjunto de especificaciones para la arquitectura, protocolos e interfaces de programación para reproductores multimedia, captura y videoconferencia Java Collaboration Especificación para la comunicación interactiva bidireccional Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java Java Telephony Especificación para aplicaciones de telefonía Java Speech Especificación para el reconocimiento y síntesis de voz Java Animation Especificación para la manipulación y movimiento de objetos bidimensionales Java 3D Especificación para la manipulación de objetos tridimensionales Java Management API Especificación para la gestión remota de redes JavaMail API Especificación para proporcionar un conjunto de clases abstractas que modelice un sistema de correo Personal Java Espeficaciones para aparatos electrónicos de consumo conectables a redes, incluyendo televisores, teléfonos inteligentes, videoconsolas, etc. Java Smart Card Especificaciones para tarjetas inteligentes, tipo tarjeta de crédito Embedded Java Especificaciones para dispositivos electrónicos industriales con software embebido ejecutándose sobre sistemas operativos de tiempo real, incluyendo dispositivos de instrumentación, electrónica de control de procesos, etc. 18. Diferencias y Similitudes con C++ Si no eres programador C++, puedes saltarte esta sección, porque no te dirá nada; Al contrario, probablemente contribuya a confundirte más que a aclararte cosas, al introducir conceptos muy familiares que entiende muy bien el que conoce C++, pero que a un profano lo dejan indiferente. Además, muchas de las cosas que se citan no se utilizan en Java, sino que se enumeran para que los programadores que aterrizan en Java desde C++ las tengan en cuenta. Por todo esto, el embrollo que se puede formar un profano puede ser mayúsculo. Si conoces C++, esta sección te servirá para tener como referencia respecto a los cambios que representa Java sobre C++, y donde debes cambiar el concepto de las cosas. Fundamentalmente, porque hay características que siguen utilizándose en Java heredadas de C++, pero el sentido con que se aplican es ligeramente diferente, lo que muchas veces lleva a los programadores C++ que atacan Java, a confusiones innecesarias. Por ello, aunque un poco denso y latoso, es una sección de lectura obligada para que tengas en cuenta las cosas que debes alterar en tu forma de concebir la programación cuando ataques proyectos en Java. Entramos en materia. Java no soporta typedefs, defines o comandos de preprocesador. Al no existir un preprocesador, no está prevista la inclusión de ficheros de cabecera, tampoco tiene cabida el concepto de macro o constante. Sin embargo, sí se permite cierto uso de constantes enumeradas a través de la utilización de la palabra clave final. Java tampoco soporta enums, aunque soporte constantes enumeradas, como acabo de decir. Java soporta clases, pero no soporta estructuras o uniones. Todas las aplicaciones C++ necesitan una función de entrada llamada main() y puede haber multitud de otras funciones, tanto funciones miembros de una Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java clase como funciones independientes. En Java no hay funciones independientes, absolutamente todas las funciones han de ser miembros de alguna clase (métodos). Funciones globales y datos globales en Java no están permitidos. En C++ se pueden crear árboles de herencia de clases independientes unos de otros. En Java esto no es posible, en última instancia hay una clase Object, de la que hereda todo lo que el programador cree. Todas las funciones o definiciones de métodos en Java deben estar contenidas dentro de la definición de la clase. Para un programador C++ puede parecerle que esto es semejante a las funciones inline, pero no es así. Java no permite, al menos directamente, que el programador pueda declarar funciones inline. Tanto Java como C++ soportan funciones o métodos (estáticos) de clases, que pueden ser invocados sin necesidad de tener que instanciar ningún objeto de la clase. En Java se introduce el concepto de interface, que no existe en C++. Una interface se utiliza para crear una clase base abstracta que contenga solamente las constantes y las declaraciones de los métodos de la clase. No se permite que haya variables miembro ni definiciones de métodos. Además, en Java también se pueden crear verdaderas clases abstractas. Java no soporta herencia múltiple, aunque se pueden utilizar las posibilidades que ofrece el uso de interfaces para emplear las ventajas que ofrece la herencia múltiple, evitando los inconvenientes que se derivan de su uso. La herencia simple es similar en Java y en C++, aunque la forma en que se implementa es bastante diferente, especialmente en lo que respecta a la utilización de los constructores en la cadena de herencia. Java no soporta la sentencia goto, aunque sea una palabra reservada. Sin embargo, soporta las sentencias break y continue con etiquetas, que no están soportadas por C++. Bajo ciertas circunstancias, estas sentencias etiquetadas se pueden utilizar como un goto encubierto. Java no soporta la sobrecarga de operadores, aunque la utilice internamente, pero no está disponible para el programador. Tampoco soporta la conversión automática de tipos, excepto en las conversiones seguras. Al contrario que C++, Java dispone de un tipo String y los objetos de este tipo no pueden modificarse. Las cadenas que se encuentren definidas entre comillas dobles son convertidas automáticamente a objetos String. Java también dispone del tipo StringBuffer, cuyos objetos sí se pueden modificar, y además se proporcionan una serie de métodos para permitir la manipulación de cadenas de este tipo. Al contrario que C++, Java trata a los arrays como objetos reales. Disponen de un miembro, length, que indica la longitud del array. Se genera una excepción cuando se intenta sobrepasar el límite indicado por esta longitud. Todos los arrays son instanciados en memoria dinámica y se permite la asignación de un array a otro; sin embargo, cuando se realiza una asignación, simplemente tenemos dos referencias a un mismo array, no hay dos copias del array, por lo que si se altera un elemento de un array, también se alterará en el otro. A diferencia de C++, el tener dos "punteros" o referencias a un mismo objeto en memoria dinámica no representa necesariamente un problema (aunque sí puede provocar resultados imprevistos). En Java, la memoria dinámica es liberada automáticamente, pero esta liberación no se lleva a cabo hasta que todas las referencias a esa memoria son NULL o dejan de existir. Por tanto, a Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java diferencia de C++, una zona de memoria dinámica nunca puede ser inválida mientras esté siendo referenciada por alguna variable. Java no soporta punteros, al menos en el sentido que atribuye C++, es decir, no permite modificar el contenido de una zona de memoria apuntada por un puntero, o realizar operaciones aritméticas con punteros. La mayor necesidad de uso de punteros deriva de la utilización de cadenas y arrays, y esto se evita al ser objetos de primera clase en Java. Por ejemplo, la declaración imprescindible en C++, char *puntero, para referenciar al primer elemento de una cadena no se necesita en Java, al ser la cadena un objeto String. La definición de clase es semejante en Java y C++, aunque en Java no es necesario el punto y coma (;) final. El operador de ámbito (::) necesario en C++ no se usa en Java, sino que se utiliza el punto (.) para construir referencias. Y, como no hay soporte de punteros, el operador flecha (->) tampoco está soportado en Java. En C++, las funciones y datos miembros se invocan utilizando el nombre de la clase y el nombre del miembro estático conectados por el operador de ámbito. En Java, se utiliza el punto (.) para conseguir el mismo propósito. Al igual que C++, Java dispone de tipos primitivos como int, float, etc. Pero, al contrario de C++, los tamaños de estos tipos son iguales independientemente de la plataforma en que se estén utilizando. No hay tipos sin signo en Java, y la comprobación de tipos es mucho más restrictiva en Java que en C++. Java dispone de un tipo boolean verdadero. Las expresiones condicionales en Java se evalúan a booleano en vez de a entero como en el caso de C++. Es decir, en Java no se permiten sentencias del tipo if( x+y ), porque la expresión que va dentro del paréntesis no se evalúa a booleano. El tipo char en C++ es un tipo de 8 bits que mapea el conjunto completo de caracteres ASCII. En Java, el tipo char es de 16 bits y utiliza el set de caracteres Unicode (los caracteres del 0 al 127 del set Unicode, coinciden con el set ASCII). Al contrario que en C++, el operador desplazamiento (>>) es un operador con signo, insertando el bit de signo en la posición vacía. Por ello, Java incorpora el operador >>>, que inserta ceros en las posiciones que van quedando vacías tras el desplazamiento. C++ permite la instanciación de variables u objetos de cualquier tipo en tiempo de compilación sobre memoria estática o, en tiempo de ejecución, sobre memoria dinámica. Sin embargo, Java requiere que todas las variables de tipos primitivos sean instanciadas en tiempo de compilación, y todos los objetos sean instanciados en memoria dinámica en tiempo de ejecución. Java proporciona clases de envoltura para todos los tipos primitivos, excepto para byte y short, que permiten que estos tipos primitivos puedan ser instanciados en memoria dinámica como objetos en tiempo de ejecución, si fuese necesario. C++ requiere que las clases y funciones estén declaradas antes de utilizarlas por primera vez. Esto no es necesario en Java. C++ también requiere que los miembros estáticos de una clase sé redeclaren fuera de la clase. Esto tampoco es necesario en Java. En C++, si no se indican valores de inicialización para las variables de tipos primitivos, pueden contener basura. Aunque las variables locales de tipos primitivos se pueden inicializar en la declaración, los datos miembros de tipo primitivo de una clase no se pueden inicializar en la definición de la clase. En Java, se pueden inicializar estos datos miembros de tipo primitivo en la declaración de la clase. También se pueden inicializar en el constructor. Si la inicialización no se realiza explícitamente, o falla por lo que Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java sea, los datos son inicializados a cero (o su equivalente) automáticamente. Al igual que ocurre en C++, Java también soporta constructores que pueden ser sobrecargados. Y, del mismo modo que sucede en C++, si no se proporciona un constructor explícitamente, el sistema proporciona un constructor por defecto. En Java todos los objetos se pasan por referencia, eliminando la necesidad del constructor copia utilizado en C++. No hay destructores en Java. La memoria que no se utiliza es devuelta al Sistema a través del reciclador de memoria, que se ejecuta en un thread diferente al del programa principal. Esta es una de las diferencias extremadamente importantes entre C++ y Java. Como C++, Java también soporta la sobrecarga de funciones. Sin embargo, el uso de argumentos por defecto no está soportado en Java. Al contrario que C++, Java no soporta templates, por lo que no existen funciones o clases genéricas. El multithreading, o multihilo, es algo característico de Java, que se proporciona por defecto. Aunque Java utiliza las mismas palabras clave que C++ para indicar el control de acceso: private, public y protected, la interpretación es significativamente diferente entre C++ y Java. La implementación del manejo de excepciones en Java es más completo y bastante diferente al empleado en C++. Al contrario que C++, Java no soporta la sobrecarga de operadores. No obstante, los operadores + y += son sobrecargados automáticamente para concatenar cadenas, o para convertir otros tipos a cadenas. Como en C++, las aplicaciones Java pueden hacer llamadas a funciones escritas en otros lenguajes, llamadas métodos nativos. No obstante, los applets no pueden hacer llamadas a métodos nativos. A diferencia de C++, Java dispone de un sistema interno de generación de documentación. Si se utilizan comentarios escritos de determinada forma, se puede utilizar la herramienta javadoc para generar la documentación de la aplicación Java, e incluso se pueden programar doclets para generar tipos específicos de documentación. 19. Java para Aplicaciones Corporativas Java actualmente está en boca de todos, Java e Intranet son las palabras de moda. Pero, surge la pregunta de sí esta es una buena tecnología para desarrollar aplicaciones corporativas. Y la respuesta es afirmativa, en donde la red sea algo crítica, Java facilita tremendamente la vida de la programación corporativa. Durante años, las grandes empresas se han convencido de que la "red" corporativa es la arteria por donde fluye la sangre que mantiene vivo su negocio. Desde el gran servidor de sus oficinas centrales, hasta los servidores de las delegaciones, las estaciones de trabajo de los programadores y la marabunta de PCs, la información va fluyendo de unos a otros. Para muchas compañías, La Red es la Empresa. Si esta red no se mantiene sana, los pedidos no llegan, el inventario no se actualiza, el software no se realiza adecuadamente, los clientes no están satisfechos y, fundamentalmente, el dinero no entra. La necesidad de diagnosticar y reducir la arteriosclerosis de la red, hace que se estén inyectando continuamente nuevas metodologías que subsanen este grave problema. ¿Es Java la medicina? Está claro que cuando vemos un cepillo animado limpiando los dientes, cubos moviéndose en 3-D, o una banda de gatos locos en applets de Java, nos convencemos de que es el lenguaje idóneo para Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java Internet. Pero, qué pasa con las aplicaciones corporativas, ¿sería una buena tecnología allí donde la red es el punto crítico? Vamos a intentar responder a esta cuestión comparando las capacidades de Java contra la lista de necesidades de la red corporativa. 20. Desarrollo rápido de aplicaciones Hace años, se decía que los programadores pronto desaparecerían. Los generadores automáticos de programas, eliminarían a los generadores humanos y el mundo sería un lugar mejor para vivir. Desdichadamente, quienes decían esto no tuvieron en cuenta la acelerada demanda de software de calidad para muy diferentes aplicaciones. La tecnología de objetos pronto vino a intentar facilitar la tarea, adoptando el modelo de "generar parte de un programa", así, generando la parte básica de un programa (los objetos), se podría conectar con otros para proporcionar diferentes utilidades al usuario. El lenguaje C++ es una buena herramienta, pero no cumple totalmente la premisa. Visual Basic y NextStep, se acercan cada vez más al poder de los objetos. Java facilita la creación de entornos de desarrollo-aplicaciones de modo similar, pero además es flexible, poderoso y efectivo. Los programadores ahora disponen de herramientas de programación de calidad, que apuntan hacia esa meta; todas se incluyen dentro de los Entornos Visuales de Desarrollo y se conocen como herramientas RAD (Rapid Application Development), como son el Java WorkShop de SunSoft, el entorno JBuilder de Borland, el Visual J++ de Microsoft, el Café de Symantec, la Jfactory de Rogue Wave, el Visual Age de IBM, el Mojo de Penumbra Software, y herramientas más sofisticadas como Netcode o FutureTense. Esto proporciona una gran progresión a los entornos de desarrollo Java. 21. Aplicaciones efectivas y eficientes Las aplicaciones que se crean en grandes empresas deben ser más efectivas que eficientes; es decir, conseguir que el programa funcione y el trabajo salga adelante es más importante que el que lo haga eficientemente. Esto no es una crítica, es una realidad de la programación corporativa. Al ser un lenguaje más simple que cualquiera de los que ahora están en el cajón de los programadores, Java permite a éstos concentrarse en la mecánica de la aplicación, en vez de pasarse horas y horas incorporando APIs para el control de las ventanas, controlando minuciosamente la memoria, sincronizando los ficheros de cabecera y corrigiendo los agónicos mensajes del linker. Java tiene su propio toolkit para interfaces, maneja por sí mismo la memoria que utilice la aplicación, no permite ficheros de cabecera separados (en aplicaciones puramente Java) y solamente usa enlace dinámico. Muchas de las implementaciones de Java actuales son puros intérpretes. Los ByteCodes son interpretados por el sistema run-time de Java, la Máquina Virtual Java (JVM), sobre el ordenador del usuario. Aunque ya hay ciertos proveedores que ofrecen compiladores nativos Just-In-Time (JIT). Si la Máquina Virtual Java dispone de un compilador instalado, las secciones (clases) del ByteCode de la aplicación se compilarán hacia la arquitectura nativa del ordenador del usuario. Los programas Java en ese momento rivalizarán con el rendimiento de programas en C++. Los compiladores JIT no se utilizan en la forma tradicional de un compilador; los programadores no compilan y distribuyen binarios Java a los usuarios. La compilación JIT tiene Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java lugar a partir del ByteCode Java, en el sistema del usuario, como una parte (opcional) del entorno run-time local de Java. Muchas veces, los programadores corporativos, ansiosos por exprimir al máximo la eficiencia de su aplicación, empiezan a hacerlo demasiado pronto en el ciclo de vida de la aplicación. Java permite algunas técnicas innovadoras de optimización. Por ejemplo, Java es inherentemente multithreaded. A la vez que ofrece posibilidades de multithread como la clase Thread y mecanismos muy sencillos de usar de sincronización, Java en sí utiliza threads. Los desarrolladores de compiladores inteligentes pueden utilizar esta característica de Java para lanzar un thread que compruebe la forma en que se está utilizando la aplicación. Más específicamente, este thread podría detectar qué métodos de una clase se están usando con más frecuencia e invocar a sucesivos niveles de optimización en tiempo de ejecución de la aplicación. Cuanto más tiempo esté corriendo la aplicación o el applet, los métodos estarán cada vez más optimizados (Guava de Softway es de este tipo). Si un compilador JIT está embebido en el entorno run-time de Java, el programador no se preocupa de hacer que la aplicación se ejecute óptimamente. Siempre he pensado que los Sistemas Operativos tendrían que aplicarse esta filosofía; un optimizador progresivo es un paso más hacia esta idea. 22. Portabilidad para programador y programa En una empresa de relativo tamaño hay una pléyade diferente de ordenadores. Probablemente nos encontremos con estaciones de trabajo Sun para el desarrollo de software, hordas de PCs para cada empleado, algún Mac en el departamento de documentación, una estación de trabajo HP en administración y una estación SGI en la sala de demos. Desarrollar aplicaciones corporativas para un grupo tan diferente de plataformas es excesivamente complejo y caro. Hasta ahora era complicado convencer a los programadores de cada arquitectura que utilizasen un API común para reducir el coste de las aplicaciones. Con un entorno run-time de Java portado a cada una de las arquitecturas de las plataformas presentes en la empresa y una buena librería de clases ("packages" en Java), los programadores pueden entenderse y encontrar muy interesante trabajar con Java. Esta posibilidad hará tender a los programadores hacia Java, justo donde otros intentos anteriores con entornos universales (como Galaxy o XVT) han fracasado. Estos APIs eran simplemente inadecuados, no orientados a redes y, verdaderamente, pesados. Una vez que los programas estén escritos en Java, otro lado interesante del asunto es que los programadores también son portables. El grupo de programadores de la empresa puede ahora enfrentarse a un desarrollo para cualquiera de las plataformas. La parte del cliente y del servidor de una aplicación estarán ahora escritas en el mismo lenguaje. Ya no será necesario tener un grupo que desarrolle en Solaris en del departamento de I+D, programadores trabajando sobre Visual Basic en el departamento de documentación y programadores sobre GNU en proyectos especiales; ahora todos ellos podrán estar juntos y formar el grupo de software de la empresa. Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java 23. Costos de Desarrollo En contraste con el alto costo de los desarrollos realizados sobre estaciones de trabajo, el costo de creación de una aplicación Java es similar al de desarrollar sobre un PC. Desarrollar utilizando un software caro para una estación de trabajo (ahora barata) es un problema en muchas empresas. La eficiencia del hardware y el poco costo de mantenimiento de una estación de trabajo Sun, por ejemplo, resulta muy atractivo para las empresas; pero el costo adicional del entorno de desarrollo con C++ es prohibitivo para la gran mayoría de ellas. La llegada de Java e Intranet reducen considerablemente estos costos. Las herramientas Java ya no están en el entorno de precios de millones de pesetas, sino a los niveles confortables de precio de las herramientas de PCs. Y con el crecimiento cada día mayor de la comunidad de desarrolladores de software freeware y shareware que incluso proporcionan el código fuente, los programadores corporativos tienen un amplio campo donde moverse y muchas oportunidades de aprender y muchos recursos a su disposición. El éxito que Internet ha proporcionado a los equipos de software corporativos es un regalo. El precio del software es ahora el mismo para un poderoso equipo corriendo Unix que para un PC. Incluso Netscape tiene al mismo precio la versión Unix de su servidor Web SuiteSpot que la versión PC/NT. Esta es la filosofía de precios que parece ser será la que se siga con las herramientas basadas en Java. 24. Mantenimiento y Soporte Un problema bien conocido que ocurre con el software corporativo es la demanda de cuidados y alimentación. Java no es, ciertamente, la cura para la enfermedad del mantenimiento, pero tiene varias características que harán la vida del enfermero más fácil. Uno de los componentes del JDK es javadoc. Si se usan ciertas convenciones en el código fuente (como comenzar un comentario con /** y terminarlo con */) Java, javadoc podrá fácilmente generar páginas HTML con el contenido de esos comentarios, que pueden visualizarse en cualquier navegador. La documentación del API de Java ha sido creada de este modo. Esto hace que el trabajo de documentar el código de nuevas clases Java sea trivial. Y más todavía con la incorporación de los doclets, que son pequeñas aplicaciones Java que permiten configurar qué información y en qué formato se va a generar, con lo cual la versatilidad de la herramienta es mucho mayor. Otro gran problema del desarrollador corporativo es la creación y control de makefiles. Leerse un makefile es como estar leyendo la historia de empresa. Normalmente se pasan de programador a programador, quitando la información que no es esencial, siempre que se puede. Esto hace que muchos de los makefiles de las aplicaciones contengan docenas de librerías, una miríada de ficheros de cabecera y ultra-confusos macros. Es como mirar en el estómago de un gran tiburón. Java reduce las dependencias de complejos makefiles drásticamente. Primero, no hay ficheros de cabecera. Java necesita que todo el código fuente de una clase se encuentre en un solo fichero. Java tiene la inteligencia de make en el propio lenguaje para simplificar la compilación de ByteCodes. Por ejemplo: public class pepe { // Fichero: pepe.java guitarra flamenca; Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java } public class guitarra { // Fichero: guitarra.java } % javac -verbose pepe.java [parsed pepe.java in 471ms] [loaded d:\jdk1.1.1\lib\classes.zip(java/lang/Object.class) in 230ms] [checking class pepe] [parsed .\guitarra.java in 30ms] [wrote pepe.class] [checking class guitarra] [wrote .\guitarra.class] [done in 3996ms] El compilador Java se da cuenta de que necesita compilar el fichero guitarra.java. Ahora se puede forzar a que recompile pepe.java sin cambiar guitarra.java, con lo que se podrá comprobar que el compilador de ByteCode Java no recompila innecesariamente el fichero guitarra.java. % javac -verbose pepe.java [parsed pepe.java in 350ms] [loaded d:\jdk1.1.1\lib\classes.zip(java/lang/Object.class) in 90ms] [checking class pepe] [loaded .\guitarra.java in 30ms] [wrote pepe.class] [done in 3054ms] Ahora, si se modifica guitarra.java (añadiendo, por ejemplo, otro miembro a la clase) y se compila pepe.java, el compilador Java se dará cuenta de que debe recompilar tanto pepe.java como guitarra.java % javac -verbose pepe.java [parsed pepe.java in 541ms] [loaded d:\jdk1.1.1\lib\classes.zip(java/lang/Object.class) in 90ms] [checking class pepe] [parsed .\guitarra.java in 41ms] [wrote pepe.class] [checking class guitarra] [wrote .\guitarra.class] [done in 3265ms] En el libro Just Java de Peter van der Linden hay un capítulo excelente acerca del compilador de Java, si el lector tiene oportunidad, no debería dejar pasarla sin leerlo. Y también a la hora de hablar de costes se encuentra el debate inexistente entre terminales y ordenadores. Es inexistente, porque ambos extremos no son excluyentes. Ni se trata de que haya que volver a la época de los grandes ordenadores enclaustrados en salas especiales a temperaturas de helarse, ni de que toda la empresa tenga ordenadores que deba actualizar cada año y medio. En general, para una empresa de investigación y desarrollo, para un estudiante o para un simple aficionado a la informática, es mucho más interesante la opción de tener un ordenador, no un terminal, por muy NetComputer que sea. Sin embargo, en el caso de empresas de no muchos empleados, en que se ejecuta como mucho Office y alguna otra aplicación propietaria, resulta prohibitivo actualizar ordenadores con esa frecuencia, pero también es Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java prohibitivo, de cara a la competitividad, el quedarse anclado en el pasado. La solución le llega, por tanto, de la mano de los NCs, o terminales en general, conectados a un ordenador potente. De esta forma, sí pueden permitirse actualizar un único equipo y además, actualizar las aplicaciones, puesto que éstas utilizarían los recursos del servidor central para ejecutarse, con la ventaja adicional de que cualquier instalación de software se realiza sobre un único equipo. Esto no quiere decir que necesariamente haya que volver a los mainframes, puesto que el problema de éstos no radicaba en el concepto, sino en el cose que podía suponer para una empresa, coste tanto de hardware como de aprendizaje. IBM con los PCs y Microsoft con Windows han contribuido a rebajar estos costes a niveles inimaginables, de modo que la solución ideal de servidores con aplicaciones facilita el manejo del software al usuario, con NCs o NetPCs conectados a ellos. 25. Aprendizaje Si la empresa está llena de programadores de C++ con alguna experiencia en el manejo de librería gráficas, aprenderán rápidamente lo esencial de Java. Si el equipo de ingenieros no conoce C++, pero maneja cualquier otro lenguaje de programación orientada a objetos, les llevará pocas semanas dominar la base de Java. Lo que sí que no es cierto es que haya que aprender C++ antes de aprender Java. Si los ingenieros de la empresa no conocen ningún lenguaje orientado a objetos, sí que tienen que aprender los fundamentos de esta tecnología antes de nada, y luego aplicarlos a la programación con Java. El análisis y diseño orientado a objetos debe ser comprendido antes de intentar nada con Java. Los programadores de Java sin un fondo de conocimientos de OOA/D producirán código pobre. Además, los libros sobre Java crecen como la espuma, ya hay más de 200 publicados, y si se busca "Progamming in Java" en la Red, encontraremos una increíble cantidad de Web sites, y lo mismo si nos dedicamos a buscar sites dedicados a "Learning Java". Y si esto no es el sustituto de un instructor humano, hay ya varias empresas que ofrecen enseñanza de Java (incluso a través de Internet), entre ellas, Sun. 26. Resumen En base a los argumentos que acabamos de exponer, ¿podría una empresa utilizar Java para sus aplicaciones críticas? En este instante, sería suficiente un acercamiento a Java. Porque más importante que la elección de Java o cualquier otro lenguaje de programación es un buen diseño de la arquitectura de la aplicación. Diseñar la aplicación para que esté distribuida entre servidores y clientes, y la línea de partida debe ser el diseño modular. Algunas sugerencias para adoptar Java como tecnología corporativa, serían: 1. Usar Java en el desarrollo de la interface del cliente; Java es suficientemente estable para desarrollar una interface portable. Utilizar herramientas de programación más estables en los servidores, porque son la parte crítica. 2. Portar o crear un servidor no-crítico en Java, de forma que tanto cliente como servidor estén escritos en Java. 3. Utilizar Java en proyectos de envergadura tanto en el cliente como en el servidor, para valorar la efectividad de Java. Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java Intranet está creciendo actualmente más rápido que Internet. Las organizaciones corporativas están adoptando la metodología Internet para proporcionar soluciones a sus usuarios y clientes. Java tiene todas las cartas para ser una herramienta de inestimable valor en el desarrollo de aplicaciones corporativas. Pero aunque Java convence y aporta argumentos para ello, no es todavía la panacea que en ocasiones Sun pretende vender. De hecho, Java no es sencillo de dominar, y no es tan rápido como otros lenguajes. Como tantas tecnologías que superan la fase de emergencia para iniciar la de consolidación, facilita las cosas, pero todavía debe mejorarse a sí mismo. De cara a la empresa y a los responsables de tecnología, lo que es cierto es que se encuentran ante dos mundos, Windows y Java, en parte complementarios pero también diferentes y, de la parte que les toca a sus respectivos fabricantes, visceralmente enfrentados. Lograr lo mejor de ambos exige la adopción de dos arquitecturas que evolucionan muy deprisa y cada una en una dirección. Situación que introduce una variable de complejidad para los equipos de desarrollo que si quieren estar a ambos lados, deberán contemplar y seguir las evoluciones de las dos plataformas que, al menos por el momento, no parece que estén dispuestas a converger. Actualmente Java se está usando cada vez más en las empresas, a pesar de los problemas de rendimiento, ya que ni los mejores compiladores JIT, que pueden acelerar la aplicación entre 10 y 20 veces, suelen acercarse al 50% del rendimiento de un programa en C. Y además se usa en los servidores, que siempre se ha dicho que tienen que ejecutar el software más rápido. Lo que ocurre es que en la vida real, un servlet que no utiliza AWT para nada y corre en una máquina virtual con JIT tiene un rendimiento aceptable; el que sea inferior a otros componentes escritos en C y utilizando FastCGI es pura anécdota mientras no se necesite ese extra de rendimiento. Y aún entonces, cabe valorar si el precio de un procesador adicional es inferior a la diferencia de coste de desarrollo y mantenimiento entre en código en C y en de Java. Sin embargo Java, por otro lado, se está introduciendo muy rápidamente en los procesos de Control Distribuido, en las empresas que trabajan con sistemas de control embebidos. Sun promociona Java diciendo que es el lenguaje ideal para este tipo de aparatos, como teléfonos móviles, tarjetas de crédito, etc. Y lo cierto es que parece que tienen razón, y en este momento sólo se está empezando. La imagen reproduce un sistema de control de papel, montado por la empresa Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java finlandesa Valmet Automation, que utiliza Java como lenguaje base para el complejo control de la producción del papel. Sus ingenieros han embebido una Máquina Virtual Java en las estaciones de control de procesos de su sistema de control distribuido Damatic XDi. La producción del papel involucra una comunicación instantánea de la maquinaria con los sensores, cada cual de un fabricante. Los paquetes de software que controlan estos sensores se ejecutaban sin el control directo del sistema de control distribuido, pero ahora, los fabricantes de los sensores, utilizando Java, pueden traspasarle el conocimiento directamente al Sistema de Control. Pero también en otras áreas se está recurriendo a Java; como por ejemplo el hospital Northern California Kaiser Permanente, que utiliza el sistema Kahuna, basado en WebChart, que emplea simultáneamente Corba y Java. Este sistema, del cual la figura siguiente reproduce algunas de sus pantallas, es empleado para la gestión de datos de pacientes, doctores, medicamentos, diagnósticos; datos que residen en gran cantidad de bases de datos distintas, con servidores y clientes corriendo en gran cantidad de plataformas diferentes; es decir, es un sistema completamente concurrente y heterogéneo; aunque el CDR (Clinical Data Repository) reside en Walnut Creek y Corona, al sur de California, en mainframes IBM, manejando los datos de casi tres millones de pacientes de todos los Estados Unidos de América. El sistema completo de WebChart fue desarrollado por 5 programadores durante 6 meses, empleando 45 días más para concluir la primera versión utilizable del sistema. Este sistema fue primero portado de Cobol a C++, pero en medio del proyecto en C++, que ya se demoraba en exceso, se cambió a Java para acelerar la velocidad de desarrollo. El sistema mantiene un histórico de datos de cada paciente con gráficas demográficas, problemas médicos significativos, alergias, inmunizaciones, histórico de visitas del paciente, hospitalizaciones del paciente, resultados del laboratorio, histórico de medicaciones, imágenes de Resonancia Magnética o Tomografía Axial Computarizada. También muestra las planificaciones tanto clínicas como de los doctores, con enlaces a las tablas de paciente. Permite acceder a los mainframes del hospital y consultar las bibliotecas de diagnósticos y de referencias de fármacos de la intranet del hospital. Y para todo lo que no se pueda conseguir a través del sistema, dispone de un emulador 3270 para acceder a los mainframes. Para acceder a toda esta información solamente es necesario disponer de un navegador con soporte Java y un módem; pudiendo verse tanto la aplicación como las complejas imágenes de radiografías o tomografías, utilizando el plugin Amicas. 27. Primeros Pasos en Java 1. Una mínima aplicación en Java ? HolaMundo ? Compilación y Ejecución de HolaMundo ? Ficheros Fuente Java ? Compilación ? Ejecución ? Problemas de Compilación ? HolaMundo en C++ 2. Un Applet básico en Java Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java ? HolaMundo ? Componentes Básicos de un Applet ? Clases Incluidas ? La clase Applet ? Métodos de Applet ? Compilación de un Applet ? Llamada a Applets ? Prueba de un Applet 3. Argumentos en la Línea de Comandos Como cualquier otro lenguaje, Java se usa para crear aplicaciones. Pero, además Java tiene la particularidad especial de poder crear aplicaciones muy especiales, son los applets, que es una mini (let) aplicación (app) diseñada para ejecutarse en un navegador. A continuación se verá en detalle lo mínimo que se puede hacer en ambos casos, lo que permitirá presentar la secuencia de edición, compilación, ejecución en Java, que será imprescindible a la hora de estudiar detalles más concretos de Java, porque los ejemplos que se muestren serán mejor comprendidos. Hay que hacer una aclaración antes de entrar a ver nada, porque muchos programadores que se introducen en Java piensan solamente en applets, pero Java va mucho más allá, y no hay por qué establecer una distinción entre applet como aplicación gráfica y aplicación independiente como aplicación de consola. No hay nada que impida a una aplicación independiente funcionar como una aplicación en modo gráfico, lo único que hay que hacer es tomarse la molestia de inicializar la ventana de la aplicación a mano y añadirle el evento de que se cierre cuando el mensaje que se lo indique le llegue, cosas en el caso de los applets están a cargo del navegador o visualizador que se esté empleando. Esto es importante, porque en este Tutorial se utilizarán fundamentalmente aplicaciones Java independientes, porque los applets tienen unas medidas de seguridad tan estrictas que no permiten muchas de las opciones del lenguaje, como por ejemplo el acceso a ficheros o la impresión de documentos. Una mínima aplicación en Java La aplicación más pequeña posible es la que simplemente imprime un mensaje en la pantalla. Tradicionalmente, el mensaje suele ser "Hola Mundo!". Esto es justamente lo que hace el siguiente fragmento de código: // Aplicación HolaMundo de ejemplo // class HolaMundoApp { public static void main( String args[] ) { System.out.println( "Hola Mundo!" ); } } HolaMundo Hay que ver en detalle la aplicación anterior, línea a línea. Esas líneas de código contienen los componentes mínimos para imprimir Hola Mundo! en la pantalla. Es un ejemplo muy simple, que no instancia objetos de ninguna otra clase; sin embargo, accede a otra clase incluida en el JDK. // Aplicación HolaMundo de ejemplo // Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java Estas dos primeras líneas son comentarios. Hay tres tipos de comentarios en Java, // es un comentario orientado a línea. class HolaMundoApp { Esta línea declara la clase HolaMundoApp. El nombre de la clase especificado en el fichero fuente se utiliza para crear un fichero nombredeclase.class en el directorio en el que se compila la aplicación. En este caso, el compilador creará un fichero llamado HolaMundoApp.class. public static void main( String args[] ) { Esta línea especifica un método que el intérprete Java busca para ejecutar en primer lugar. Igual que en otros lenguajes, Java utiliza una palabra clave main para especificar la primera función a ejecutar. En este ejemplo tan simple no se pasan argumentos. public significa que el método main() puede ser llamado por cualquiera, incluyendo el intérprete Java. static es una palabra clave que le dice al compilador que main se refiere a la propia clase HolaMundoApp y no a ninguna instancia de la clase. De esta forma, si alguien intenta hacer otra instancia de la clase, el método main() no se instanciaría. void indica que main() no devuelve nada. Esto es importante ya que Java realiza una estricta comprobación de tipos, incluyendo los tipos que se ha declarado que devuelven los métodos. args[] es la declaración de un array de Strings. Estos son los argumentos escritos tras el nombre de la clase en la línea de comandos: %java HolaMundoApp arg1 arg2 ... System.out.println( "Hola Mundo!" ); Esta es la funcionalidad de la aplicación. Esta línea muestra el uso de un nombre de clase y método. Se usa el método println() de la clase out que está en el paquete System. A una variable de tipo class se puede acceder sin necesidad de instanciar ningún objeto de esa clase. Por ello ha de ser un tipo básico o primitivo, o bien puede ser una referencia que apunta a otro objeto. En este caso, la variable out es una referencia que apunta a un objeto de otro tipo, aquí una instancia de la clase PrintStream (un objeto PrintStream), que es automáticamente instanciado cuando la clase System es cargada en la aplicación. Esto es algo semejante al hecho de que los objetos stream de entrada/salida, cin y cout son automáticamente instanciados y enlazados a los dispositivos estándar de entrada y salida cuando un programa C++ comienza su ejecución. El método println() toma una cadena como argumento y la escribe en el stream de salida estándar; en este caso, la ventana donde se lanza la aplicación. La clase PrintStream tiene un método instanciable llamado println(), que lo hace e presentar en la salida estándar del Sistema el argumento que se le pase. En este caso, se utiliza la variable o instancia de out para acceder al método. } } Finalmente, se cierran las llaves que limitan el método main() y la clase HolaMundoApp. En C++, la función main() en un programa puede tener cualquiera de los siguientes prototipos: tipo_retorno main() tipo_retorno main( int argc,char argv[] ) Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java El tipo_retorno puede ser cualquier tipo válido, o void, para indicar que la función no tiene que devolver valor alguno. La lista de argumentos puede estar vacía, o contener los argumentos de soporte para pasar parámetros en la línea de comandos. Esta forma de implementación la función difiere de la que acaba de presentar para Java, que siempre habrá de ser la misma, independientemente de los valores de retorno o la lista de parámetros que se pasen en la lista de argumentos a la aplicación. Compilación y Ejecución de HolaMundo A continuación se puede ver el resultado de esta primera y sencilla aplicación Java en pantalla. Se genera un fichero con el código fuente de la aplicación, se compilará y se utilizará el intérprete Java para ejecutarlo. Ficheros Fuente Java Los ficheros fuente en Java terminan con la extensión ".java". Crear un fichero utilizando cualquier editor de texto ascii que tenga como contenido el código de las ocho líneas de nuestra mínima aplicación, y salvarlo en un fichero con el nombre de HolaMundoApp.java. Para crear los ficheros con código fuente Java no es necesario un procesador de textos, aunque puede utilizarse siempre que tenga salida a fichero de texto plano o ascii, sino que es suficiente con cualquier otro editor. Compilación El compilador javac se encuentra en el directorio bin por debajo del directorio java, donde se haya instalado el JDK. Este directorio bin, si se han seguido las instrucciones de instalación, debería formar parte de la variable de entorno PATH del sistema. Si no es así, tendría que revisar la Instalación del JDK. El compilador de Java traslada el código fuente Java a byte-codes, que son los componentes que entiende la Máquina Virtual Java que está incluida en los navegadores con soporte Java y en appletviewer. Una vez creado el fichero fuente HolaMundoApp.java, se puede compilar con la línea siguiente: %javac HolaMundoApp.java Si no se han cometido errores al teclear ni se han tenido problemas con el path al fichero fuente ni al compilador, no debería aparecer mensaje alguno en la pantalla, y cuando vuelva a aparecer el prompt del sistema, se debería ver un fichero HolaMundoApp.class nuevo en el directorio donde se encuentra el fichero fuente. Si ha habido algún problema, en Problemas de compilación al final de esta sección, hemos intentado reproducir los que más frecuentemente se suelen dar, se pueden consultar por si pueden aportar un poco de luz al error que haya aparecido. Ejecución Para ejecutar la aplicación HolaMundoApp, hemos de recurrir al intérprete java, que también se encuentra en el directorio bin, bajo el directorio en donde se haya instalado el JDK. Se ejecutará la aplicación con la línea: %java HolaMundoApp y debería aparecer en pantalla la respuesta de Java: %Hola Mundo! El símbolo % representa al prompt del sistema, y se utilizará aquí para presentar las respuestas que devuelva el sistema como resultado de la ejecución de los comandos que se introduzcan por teclado o para indicar las líneas de comandos a introducir. Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java Cuando se ejecuta una aplicación Java, el intérprete Java busca e invoca al método main() de la clase cuyo nombre coincida con el nombre del fichero .class que se indique en la línea de comandos. En el ejemplo, se indica al Sistema Operativo que arranque el intérprete Java y luego se indica al intérprete Java que busque y ejecute el método main() de la aplicación Java almacenada en el fichero HolaMundoApp.class. Problemas de compilación A continuación se encuentra una lista de los errores más frecuentes que se presentan a la hora de compilar un fichero con código fuente Java, tomando como base los errores provocados sobre la mínima aplicación Java que se está utilizando como ejemplo, pero también podría generalizarse sin demasiados problemas. %javac: Command not found No se ha establecido correctamente la variable PATH del sistema para el compilador javac. El compilador javac se encuentra en el directorio bin, que cuelga del directorio donde se haya instalado el JDK (Java Development Kit). %HolaMundoApp.java:3: Method printl(java.lang.String) not found in class java.io.PrintStream. System.out.printl( "HolaMundo! ); ^ Error tipográfico, el método es println no printl. %In class HolaMundoApp: main must be public and static Error de ejecución, se olvidó colocar la palabra static en la declaración del método main de la aplicación. %Can´t find class HolaMundoApp Este es un error muy sutil. Generalmente significa que el nombre de la clase es distinto al del fichero que contiene el código fuente, con lo cual el fichero nombre_fichero.class que se genera es diferente del que cabría esperar. Por ejemplo, si en el fichero de código fuente de la aplicación HolaMundoApp.java se coloca en vez de la declaración actual de la clase HolaMundoApp, la línea: class HolaMundoapp { se creará un fichero HolaMundoapp.class, que es diferente del HolaMundoApp.class, que es el nombre esperado de la clase; la diferencia se encuentra en la a minúscula y mayúscula. %Note: prueba.java uses a deprecated API. Recompile with "-deprecation" for details. 1 Warning Esto es originado por otra de las cosas que ha introducido el JDK 1.1 como son los elementos obsoletos (deprecated), es decir, aquellas clases o métodos que no se recomienda utilizar, aunque sigan siendo válidos, porque están destinados a desaparecer de la faz de la Tierra a partir de alguna de las versiones posteriores del JDK. Si se compila un programa que hace uso de uno de estas clases, o bien utiliza o sobrecarga un método obsoleto, el compilador mostrará un mensaje de este tipo. Solamente se genera un aviso por módulo, independientemente del número de métodos obsoletos que se estén utilizanzo, por eso hay que seguir la recomendación del aviso si se quiren saber los detalles completos de todas las clases y métodos obsoletos que se están utilizando. La llamada a estos métodos rara vez tiene excusa, aunque haya casos especiales en que se escriba código para que sea llamado tanto por programas generados con la versión 1.0 del JDK y con la versión 1.1 o 1.2, En este caso JavaSoft Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java recomienda indicarle al compilador que se está haciendo uso intencionado del método obsoleto, y esto se consigue colocando el comentario /** @deprecated */ justo antes del método sobrecargado, por ejemplo: /** @deprecated */ public boolean handleEvent( Event evt ) { if( evt.id == Event.WINDOW_DESTROY ) System.exit( 0 ); return( false ); } No obstante, en este caso y a pesar de estos avisos, el compilador genera código perfectamente ejecutable. HolaMundo en C++ Para poder establecer comparaciones, y en deferencia a los programadores que dominen C++, se muestran a continuación dos versiones C++ de la pequeña aplicación que se ha empleado para imprimir el mensaje de saludo en la pantalla. La primera versión, HolaA.cpp, presenta en pantalla el consabido mensaje "Hola Mundo!", pero en el código no se utilizan clases y es significativamente diferente al programa Java que se ha discutido hasta ahora. En Java no se puede escribir nada semejante. #include <iostream.h> void main() { // Presenta el mensaje en pantalla cout << "Hola Mundo!"; } Cuando se compila y ejecuta el fichero ejecutable resultante, el mensaje de saludo aparece en la pantalla. Pero se puede crear una nueva versión del programa C++, HolaB.cpp, estructurada de forma semejante a lo que se hace en Java. Así, esta segunda versión de la aplicación ya contiene una clase, que tiene una función miembro estática que es la encargada de presentar el mensaje de saludo en pantalla. Como en Java, las funciones miembro se pueden invocar sin necesidad de instanciar ningún objeto de la clase. #include <iostream.h> // Se define la clase HolaB class HolaB { public: // Se define una función estática para presentar // la cadena static void presentarMensaje() { // Presenta el mensaje en la pantalla cout << "Hola Mundo!"; } }; // Se llama a la función miembro estática, sin ningún // objeto, para presentar el mensaje en pantalla void main() { HolaB::presentarMensaje(); Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java } Teniendo en cuenta las tres versiones de la aplicación a la vez, se puede observar claramente la orientación a objetos que está incluida en Java y la forma en que esto se demuestra, incluso en una aplicación tan sencilla como la que se limita a presentar un mensaje en pantalla. Un Applet básico en Java A continuación se trata de crear el código fuente de un applet que sea sencillo y sirva para mostrar el ciclo de desarrollo de escritura del código fuente Java, compilación, ejecución y visualización de resultados, es decir, un applet que presente un mensaje de saludo en la pantalla (la originalidad al poder!). Recuérdese que Java utiliza la extensión .java para designar los ficheros fuente. La programación de applets Java difiere significativamente de la aplicación de aplicaciones Java. Se puede prever que cuando haya necesidades de un interface gráfico, la programación de applets será bastante más sencilla que la programación de aplicaciones que realicen los mismos cometidos, aunque los applets necesiten de un visualizador de ficheros html con soporte Java, para poder ejecutarse. HolaMundo A continuación está el código fuente del applet HolaMundo, que es la versión applet de la mínima aplicación Java que antes se ha presentado y desarrollado tanto como aplicación Java como en su versión C++. Este código se guardará en un fichero fuente Java como HolaMundo.java, y que como todos los ejemplos de código que se incorporan en este Tutorial, se pueden encontrar ya preescritos y se pueden cargar directamente en el navegador (los .html) o compilar (los .java). import java.awt.Graphics; import java.applet.Applet; public class HolaMundo extends Applet { public void paint( Graphics g ) { // Pinta el mensaje en la posición indicada g.drawString( "Hola Mundo!",25,25 ); } } Componentes básicos de un Applet El lenguaje Java implementa un modelo de Programación Orientada a Objetos. Los objetos sirven de bloques centrales de construcción de los programas Java. De la misma forma que otros lenguajes de programación, Java tiene variables de estado y métodos. La descomposición de un applet en sus piezas/objetos, sería la que se muestra a continuación: /* Sección de importaciones */ public class NombreDelNuevoApplet extends Applet { /* Aquí se declaran las variables de estado (public y private) */ /* Los métodos para la interacción con los objetos se Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java declaran y definen aquí */ public void MetodoUno( parámetros ) { /* Aquí viene para cada método, el código Java que desempeña la tarea. Qué código se use depende del applet */ } } Para HolaMundo, se importan las dos clases que necesita. No hay variables de estado, y sólo se tiene que definir un método para que el applet tenga el comportamiento esperado. Clases Incluidas El comando import carga otras clases dentro del código fuente. El importar una clase desde un paquete de Java hace que esa clase importada esté disponible para todo el código incluido en el fichero fuente Java que la importa. Por ejemplo, en el applet HolaMundo que se esta presentando aquí, se importa la clase java.awt.Graphics, y se podrá llamar a los métodos de esta clase desde cualquiera de los métodos que se encuentren incluidos en el fichero HolaMundo.java. Esta clase define una área gráfica y métodos para poder dibujar dentro de ella. La función, método, paint() declara a g como un objeto de tipo Graphics; luego, paint() usa el método drawString() de la clase Graphics para generar su salida. La Clase Applet Se puede crear una nueva clase, en este caso HolaMundo, extendiendo la clase básica de Java: Applet. De esta forma, se hereda todo lo necesario para crear un applet. Modificando determinados métodos del applet, se puede lograr que lleve a cabo las funciones que se desee. import java.applet.Applet; ... public class HolaMundo extends Applet { Métodos de Applet La parte del applet a modificar es el método paint(). En la clase Applet, se llama al método paint() cada vez que el método arranca o necesita ser refrescado, pero no hace nada. En este caso, del applet básico que se está gestando, lo que se hace es: public void paint( Graphics g ) { g.drawString( "Hola Mundo!",25,25 ); } De acuerdo a las normas de sobrecarga, se ejecutará este último paint() y no el paint() vacío de la clase Applet. Luego, aquí se ejecuta el método drawString(), que le dice al applet cómo debe aparecer un texto en el área de dibujo. Otros métodos básicos para dibujar son: drawLine( int x1,int y1,int x2,int y2 ) drawRect( int x,int y,int ancho,int alto ) drawOval( int x,int y,int ancho,int alto ) Tanto para drawRect() como para drawOval(), las coordenadas (x,y) son la esquina superior izquierda del rectángulo (para drawOval(), el óvalo es encajado en el rectángulo que lo circunscribe). Rodolfo-J. Rodríguez-R. E-mail: [email protected] Manual de Java Compilación de un Applet Ahora que ya está el código del applet básico escrito y el fichero fuente Java que lo contiene guardado en disco, es necesario compilarlo y obtener un fichero .class ejecutable. Se utiliza el compilador Java, javac, para realizar la tarea. El comando de compilación será: %javac HolaMundo.java Eso es todo. El compilador javac generará un fichero HolaMundo.class que podrá ser llamado desde cualquier navegador con soporte Java y, por tanto, capaz de ejecutar applets Java. Llamada a Applets ¿Qué tienen de especial HotJava, Microsoft Explorer o Netscape con respecto a otros navegadores? Con ellos se puede ver código escrito en lenguaje html básico y acceder a todo el texto, gráfico, sonido e hipertexto que se pueda ver con cualquier otro navegador. Pero además, y esto es lo que tienen de especial, pueden ejecutar applets, que no es html estándar. Ambos navegadores entienden código html que lleve la marca <APPLET>: <APPLET CODE="SuCodigo.class" WIDTH=100 HEIGHT=50> </APPLET> Esta marca html llama al applet SuCodigo.class y establece su ancho y alto inicial. Cuando se acceda a la página Web donde se encuentre incluida la marca, se ejecutará el byte-code contenido en SuCodigo.class, obteniéndose el resultado de la ejecución del applet en la ventana del navegador, con soporte Java, que se esté utilizando. Si no se dispone de ningún navegador, se puede utilizar el visor de applets que proporciona Sun con el JDK, el appletviewer, que además requiere muchos menos recursos de la máquina en que se esté ejecutando, que cualquier otro de los navegadores que se acaban de citar. Prueba de un Applet El JDK, Kit de Desarrollo de Java, incluye el visor de applets básico, appletviewer, que puede utilizarse para la visualización rápida y prueba de applets. La ejecución de un applet sobre appletviewer se realiza a través de la llamada: %appletviewer fichero.html En este caso el fichero con el código html que ejecutará el applet HolaMundo es HolaMundo.html que generará la salida que muestra la figura. Rodolfo-J. Rodríguez-R. E-mail: [email protected]