El proyecto Jigsaw de Java 8
Una de los cambios más importantes que se están cocinando en Java 8 y no, no son los closures, es el proyecto Jigsaw que busca llenar uno de los huecos más importantes de la plataforma hasta el momento: la modularidad.
Entendiendo por modularidad el hecho de poder dividir tus aplicaciones en módulos que puedan cargarse de forma independiente y depender entre sí. Lo importante de esto para nosotros los programadores es que podremos librarnos del jar hell, el típico escenario donde tenemos en nuestro proyecto varias versiones de una misma biblioteca y no hay forma de especificar que para cierta parte de nuestra aplicación necesitamos X versión y para otra, Y.
Además de mejorar la mantenibilidad y la encapsulación de nuestra aplicación porque, en teoría, podríamos tener módulos poco acoplados entre sí. Por lo que podríamos hacer cambios dentro de uno, minimizando el impacto de estos cambios ya que los modulos dependerían entre sí sólo a través del contrato público especificado para cada uno.
Mark Reinhold, el líder del proyecto en Oracle, ha publicado un documento: Proyect Jigsaw, the Big Picture - DRAFT 1 donde presenta un resumen de los objetivos del proyecto así de cómo piensan lograrlos.
En el documento, se presentan los principios de diseño de Jigsaw:
- La modularidad es un constructor del lenguaje. Se extenderá el lenguaje Java para soportar módulos, de tal forma que así como se tienen clases e interfaces, ahora también habrá módulos.
- Los límites de los módulos deben fomentarse. Los módulos deben de definir la visibilidad de sus clases e interfases así como limitar su acceso de acuerdo a dicha visibilidad.
- Es suficiente resolver los módulos de forma estática y con una sola versión. La mayoría de las aplicaciones no necesitan quitar/poner módulos en tiempo de ejecución o tener varios módulos con diferentes versiones ejecutándose al mismo tiempo; por lo que Jigsaw se enfocará a cargar aplicaciones que no lo requieran; aunque se buscará que también soporte los otros escenarios.
Las fases en que Java resolverá los módulos:
- Compilación
- Instalación. Si usas algun servidor que tenga módulos preinstalados, Java los encontrará cuando instales tu aplicación en él.
- Ejecución. Java será capaz de encontrar de forma dínamica y en tiempo de ejecución los módulos de los que depende tu aplicación.
Por default, los módulos se declararán en un archivo llamado module-info.java y tendrán la siguiente estructura:
module foo @ 1.0 { //declara un módulo y su versión exports foo; //declara que este módulo exporta las clases en el paquete foo } module bar { requires public foo; // Re exporta los tipos exportados por foo } module baz { requires bar @ >= 1.0; // Declara dependencia al módulo bar, versiones 1.0 o superiores class baz.Main //declara la clase de entrada al módulo }
Existen otros tipos, como Views y otras opciones como declarar dependencias opcionales, las puedes ver en el Draft de Reinhold.
Jigsaw, como puedes ver, es uno de los cambios más importantes a la plataforma Java de los últimos años.
Otros han intentado con moderado éxito hacerlo: OSGi es sin duda la iniciativa más importante para agregar modularidad a Java y si bien ha tenido cierto éxito, sobre todo dentro de la fundación Eclipse donde es el sistema usado para la gestión de plugins, no ha terminado de llegar al mainstream dado que resulta complejo de gestionar por toda la "magia" de class loaders que tiene que hacer por detrás, en su momento SpringSource buscó llevarlo a sus servidores y a sus librerías pero ha dejado de lado ese intento por dicha complejidad añadida.
JBoss Modules es otra iniciativa que busca lo mismo y que es usado dentro de su servidor de aplicaciones y ahora Ceylon, el lenguaje que desarrolla dicha empresa, también tiene una propuesta para módulos (basada en JBoss Modules) que tiene además un sistema de repositorios para que, como lo hace el sistema de paquetes de Debian, las gems de Ruby o el mismo Maven, se puedan bajar los módulos de servidores.
Una de las ventajas de Jigsaw sobre estos, es que no será una librería construida encima de Java, sino estará directamente en la plataforma, con lo que podría resolver el problema de complejidad excesiva en los class loaders con los que estas se han encontrado.
¿Qué te parece esta nueva iniciativa? ¿Te ves a ti mismo usándola activamente una vez sea publicada?
Reader Comments (16)
Hola Eric,
A bote pronto, ¿qué diferencia tiene esto sobre paquetes jar?
Yo puedo crear un jar y dejarlo en el servidor, varias aplicaciones pueden nutrirse del mismo, ¿qué diferencia existe entre estas librerías y los módulos?
Saludos,
Como dice ecamacho, la principal diferencia es que con jar's y una aplicación que use terceras bibliotecas, te puedes encontrar con que dos bibliotecas (jar) usan una tercera, pero cada una usa una versión distinta de esa tercera biblioteca, y, a veces, pueden no ser compatibles entre sí, o que no encuentres una versión con la que las dos primeras funcionen correctamente.
Compararlo o contraponerlo a los .jar es extraño puesto que los .jar van a seguir estando. Por hacer una analogía, es como si el sistema de dependencias estilo Maven/Ivy estuviera integrado a nivel del lenguaje, algo parecido a lo que hace Grape con anotaciones en Groovy pero más completo por que puede implementarse a bajo nivel.
No hay que olvidar que el primer objetivo de JigSaw es modularizar el JSE, para no tener que descargarse o arrancar toda la librería de clases si no se necesita. Lo de poder usarlo en las aplicaciones es más secundario que un objetivo específico.
Donde va a facilitar la vida es en el manejo del classpath ya que podrás tener aplicaciones diferentes que podrán usar versiones distintas de la misma librería de una forma más sencilla, sin pisarse la una a la otra por usar el mismo classpath.
Pero cosas como que una librería que uses en tu aplicación requiera una versión de la librería y otra use una versión incompatible no creo que lo solucione, al menos por lo que yo entendí del proyecto.
Una vez dicho esto, no entiendo en que tiene que facilitar la vida o no en cuanto a los ClassLoaders.
Efectivamente, ahora entre módulos "todo el mundo no vea todo el mundo", sino que un módulo sólo ve a los módulos de los cuales declara dependencias. Esto permite organizar bastante mejor las dependencias entre distintos módulos, y permite que dos módulos diferentes dependan de dos versiones diferentes de un tercer módulo.
Yo personalmente nombré usando mucho esta característica por la naturaleza de mis proyectos. Lo que sí me va a venir muy bien son los superpackages.
Así es, como dice Coutmeier te permite versionar tus librerías y más aún, te permite definir sus dependencias. Así que por ejemplo, cuando agregas Hibernate que depende de varías otras librerías, ya no tendrás que ir a su sitio a buscar las dependencias o usar maven/ivy para traértelas. Jigsaw te avisará cuales son necesarias y reusará las que ya tengas en tu proyecto. En un futuro, se espera que además las descargue automáticamente.
Otro tema interesante es el tema del encapsulamiento. En el caso del uso de jars si tienes unas clases empaquetadas, tu app puede acceder a cualquier clase pública de ese jar (o protegida si les pones el mismo paquete). En el caso de los módulos no basta con eso, esas clases deben haber sido "exportadas" en el módulo para que sean visibiles y accesibles desde quien lo use.
En Jigsaw busca Simultaneous multiples versions, verás cómo lo que comentaba (aunque con muchas limitaciones) es, precisamente, uno de los objetivos. Espero esta característica desde que oí hablar de Jigsaw hace ya casi dos años, sobre todo por el caos que se monta cuando usas bibliotecas de terceros.
Pues yo a bote pronto, sin mirar más que lo que ha dicho Eric, no me gusta.
Creo que hubiera sido mejor intentar usar y/o mejorar el sistema que tiene NetBeans (basado en jars y manifest), o por lo menos declarar los módulos usando manifest files, y no crear otro tipo de fichero nuevo del cual habrá que aprender su sintaxis, necesitarán otro scanner/parser, etc....
En mi humilde opinión los manifest podrían valer, porque al final, poco a poco la simplicidad y "belleza" del java se va perdiendo, parece que lo que está de "moda" es ir metiendo más y más cosas nuevas, pero sin extender lo que ya se tiene.
Un saludo.
Ok, gracias tíos.
¿Dónde están las mujeres? Sólo opinan chicos, de verdad.
@Countermeier: Lo había leido, y sigo pensando que eso no significa que podrás usar en la misma aplicación dos librerías que dependan de versiones incompatibles de una tercera. Ojalá, pero yo no lo entiendo así.
Por lo que se dice en el documento yo entiendo que sí, pero en el contexto del módulo (de ahí las limitaciones), claro, no en el contexto global de la aplicación.
Es decir, que si uno de los módulos de la aplicación necesita la versión 1.0 de otro módulo, la podrá utilizar, aunque otro módulo (no referenciado por el actual) haya cargado la versión 2.0, ya que entre ambos módulos no se habrían producido incompatibilidades.
Funcionarían, hasta cierto punto, como compartimentos estancos.
Ahora lo entiendo. Supongo que mientras no exporten esas dependencias, por aquello de que el codigo de terceros no sabría cual usar si ambos exportan dependencias incompatibles, quizá sí pueda funcionar. Aunque eso implica un caco de classloaders de aupa... claro que mientras lo implementen ellos a nivel de lenguaje :).
Habrá que ver si luego eso no facilita los leaks debidos a dependencias ocultas...
Hola,
Varios comentarios:
Primero OSGi éxito moderado?? Ahora vas a eBay y le preguntas como gestiona las dependencias, y sólo nombras algunos, spring pertenece a VMWare y lo que están haciendo es migrar proyectos a donde creen que pueden tener más participación de ahí que hayan cedido el código de spring dm a eclipse y haya nacido Virgo, echadle un ojo, pero no sólo a ese también tenemos Apache Geronimo, creo recordar q está en la misma línea y a día de hoy es la única solución modular en Java real.
Por otro lado no se podrán cargar dos o más jar iguales pero de diferentes versiones, al menos al principio, esta fue una pregunta muy repetida durante JavaOne 2011, por tanto la solución queda como apache http server y sus módulos para en una instslacion especifica que puedas distribuir lo q realmente necesitas, pero quién se encarga de eliminar jars a día de hoy para optimizar?? Pues sólo en determinados dispositivos en los que la capacidad es un problema en mi opinión....
* Y todavía muchos decenas de años sin label, goto ni unsigned ni ASM assembler de bytecodes.
* Ya sabéis, un JDK sin las piezas esenciales deja al desarrollador con un estrés enorme, es como si estuviera tirandose el libro de Aho-Sethi-Ullman a la basura y poniéndose el libro del zionismo malvado disfrazado.
-- JCPM --
¿Modularidad? ¿no se dijo que la "modularidad" era uno de los objetivos de la OO? Cada clase era modular con respecto a las otras clases. Pues ahora resulta que esto ya es versionitis y no modularidad.
-- JCPM --
Una cosa es la modularidad y otra cosa la programación orientada a objetos con los conceptos de herencia, polimorfismo, abstracción y encapsulamiento... si quieres algún ejemplo te lo podemos dar...
Y qué tendrá que ver un goto o un label con esta conversación...
Modularidad es tan sencillo como que ahora mismo tiene un classpath en el que vas cargando todo, y por qué no tener un classpath dependiente de qué estés ejecutando, entre otras cosas eso bajo mi punto de vista es más óptimo, tener sólo lo que necesitas en cada momento...
Perdonadme que atreva a decirlo así, pero vaya lio tenéis aquí, habéis mezclado un montón de cosas sin dejar muy claro este tema. A ver si yo lo termino de liar o lo puedo aclarar un poco:
¿El engaño de java? No permite construir aplicaciones modulares debido, fundamentalmente, a su cargador de clases, y a que no están bien definidas las dependencias entre lo que se podrían llamar módulos ".jars". Me explico:
- Si tenemos 2 aplicaciones, como ponéis en alguna entrada, usando el mismo componente, más vale que sea la misma versión, si no queremos tener problemas, verdad?
- Pero además, que pasa si necesito modificar uno de los módulo de mi ear? Parada de la aplicación?
- Y como tengo que desplegar una aplicación ear completa? Con todos mis módulos, aunque nos lo use?
- Y cuando me entero de que no se satisfacen muchas de las dependencias. En runtime?
- Y como sé si están funcionando o no bien mis componentes?
Todas estas cosas y más es lo que pretende resolver OSGi, en general cualquier arquitectura orientada al servicio.
Con OSGi, se pueden construir aplicaciones modulares, definiendo un módulo con un grano más adecuado y en donde queden todas las dependencias definidas perfectamente cuando un módulo se va a desplegar, arreglando entre otras cosas, pero fundamentalmente, el cargador de clases de java. Con OSGi podríamos:
- Tener varias versiones de un mismo jar desplegadas sobre la misma plataforma. Cada módulo utilizaría la definida en sus dependencias sin problemas de clases.
- Promovemos la programación entre varios equipo al estar las funcionalidades mejor asiladas.
- Podríamos desplegar nuevas funcionalidades sin parar del todo el sistema.
- Podemos arrancar los módulos que son necesarios, adaptándonos mejor al sistema donde tenemos que ejecutar.
Como yo lo veo, con la inyección de dependencias, con Spring sobre todo, revolucionamos el mundo, el siguiente paso, sin ninguna duda se llama OSGi.