Modulos en java
Java

Modulos en java: ¿Que son? y ¿Para que se utilizan?

Compártelo

Los Modulos en Java

En este artículo, presento los modulos en Java 9 (JPMS), la nueva tecnología de ingeniería de software más importante en Java desde su inicio. La modularidad, el resultado de Project Jigsaw, ayuda a los desarrolladores en todos los niveles a ser más productivos a medida que crean, mantienen y desarrollan sistemas de software, especialmente sistemas grandes.

También te puede interesar:

¿Qué es un módulo?

La modularidad agrega un mayor nivel de agregación por encima de los paquetes. El nuevo elemento clave del lenguaje es el módulo: un grupo único y reutilizable de paquetes relacionados, así como recursos (como imágenes y archivos XML) y un descriptor de módulo que especifica el nombre del módulo.

Las dependencias del módulo (es decir, otros módulos de los que depende este módulo) los paquetes que pone explícitamente a disposición de otros módulos (todos los demás paquetes en el módulo están implícitamente no disponibles para otros módulos).

Historia

La plataforma Java SE ha existido desde 1995. Actualmente hay aproximadamente 10 millones de desarrolladores que la usan para construir desde aplicaciones pequeñas para dispositivos con recursos limitados, como aquellos en el Internet of Things (IoT) y otros dispositivos integrados, hasta grandes dispositivos.

Existen enormes cantidades de código heredado, pero hasta ahora, la plataforma Java ha sido principalmente una solución única monolítica para todos los tamaños. A lo largo de los años, se han llevado a cabo varios esfuerzos orientados a modularizar Java, pero ninguno se usa ampliamente, y ninguno se puede usar para modularizar la plataforma Java.

La modificación de la plataforma Java SE ha sido difícil de implementar, y el esfuerzo ha llevado muchos años. JSR 277: Java Module System fue propuesto originalmente en 2005 para Java 7. Este JSR fue reemplazado posteriormente por JSR 376: Java Platform Module System y dirigido a Java 8. La plataforma Java SE ahora está modularizada en Java 9, pero solo después de Java 9 se retrasó hasta septiembre de 2017.

Metas

Cada módulo debe declarar explícitamente sus dependencias.

De acuerdo con JSR 376, los objetivos clave de la modularización de la plataforma Java SE son:

Configuración confiable: la modularidad proporciona mecanismos para declarar explícitamente dependencias entre módulos de una manera que se reconoce tanto en tiempo de compilación como de ejecución. El sistema puede recorrer estas dependencias para determinar el subconjunto de todos los módulos necesarios para respaldar su aplicación.

Encapsulación fuerte: los paquetes en un módulo solo son accesibles a otros módulos si el módulo los exporta explícitamente. Incluso entonces, otro módulo no puede usar esos paquetes a menos que indique explícitamente que requiere las capacidades del otro módulo.

Esto mejora la seguridad de la plataforma porque los atacantes potenciales tienen menos clases disponibles. Puede encontrar que considerar la modularidad lo ayuda a obtener diseños más limpios y más lógicos.

Plataforma Java escalable: anteriormente, la plataforma Java era un monolito que consistía en una gran cantidad de paquetes, lo que dificultaba el desarrollo, el mantenimiento y la evolución.

No podría ser subconjunto fácilmente. La plataforma ahora está modularizada en 95 módulos (este número podría cambiar a medida que Java evoluciona). Puede crear tiempos de ejecución personalizados que constan de los únicos módulos que necesita para sus aplicaciones o los dispositivos a los que apunta.

Por ejemplo, si un dispositivo no admite GUI, puede crear un tiempo de ejecución que no incluya los módulos de GUI, lo que reduce significativamente el tamaño del tiempo de ejecución.

Mayor integridad de la plataforma: antes de Java 9, era posible usar muchas clases en la plataforma que no estaban pensadas para el uso de las clases de una aplicación. Con una fuerte encapsulación, estas API internas están realmente encapsuladas y ocultas para las aplicaciones que usan la plataforma.

Esto puede hacer que migrar el código heredado a Java 9 modularizado sea problemático si su código depende de las API internas.

Rendimiento mejorado: la JVM utiliza varias técnicas de optimización para mejorar el rendimiento de la aplicación. JSR 376 indica que estas técnicas son más efectivas cuando se sabe de antemano que los tipos necesarios se encuentran solo en módulos específicos.

Listado de los módulos de JDK

  • JEP 200: EL JDK MODULAR
  • JEP 201: CÓDIGO DE FUENTE MODULAR
  • JEP 220: IMÁGENES DE TIEMPO DE FUNCIONAMIENTO MODULARES
  • JEP 260: ENCAPSULAR LA APIS MÁS INTERNA
  • JEP 261: SISTEMA DE MODULOS
  • JEP 275: EMPAQUETADO DE APLICACIÓN MODULAR DE JAVA
  • JEP 282: JLINK: EL ENLACE DE JAVA
  • JSR 376: SISTEMA DE MÓDULO DE PLATAFORMA JAVA
  • JSR 379: JAVA SE 9

JEPs y JSR de modulación de Java

Un aspecto crucial de Java 9 es dividir el JDK en módulos para admitir varias configuraciones. (Consulte “JEP 200: The Modular JDK”. Todos los JEP y JSR de modularidad Java se muestran en la Tabla 1). Usando el comando java de la carpeta bin del JDK con la opción –list-modules, como en:

java –list-modules

Este enumera el conjunto de módulos del JDK, que incluye los módulos estándar que implementan la especificación Java Language SE (nombres que comienzan con java), módulos JavaFX (nombres que comienzan con javafx), módulos específicos JDK (nombres que comienzan con jdk) y módulos específicos de Oracle (nombres que comienzan con el oráculo). Cada nombre de módulo es seguido por una cadena de versión- @ 9 indica que el módulo pertenece a Java 9.

Declaraciones del módulo

Como mencionamos, un módulo debe proporcionar un módulo descriptor-metadata que especifique las dependencias del módulo, los paquetes que el módulo pone a disposición de otros módulos, y más.

Un descriptor de módulo es la versión compilada de una declaración de módulo que está definida en un archivo llamado module-info.java. Cada declaración de módulo comienza con el módulo de palabra clave, seguido de un nombre de módulo único y un cuerpo de módulo entre llaves, como en:

Una motivación clave del sistema de módulos es una fuerte encapsulación.

module modulename {
}

El cuerpo de la declaración del módulo puede estar vacío o puede contener varias directivas de módulos, incluyendo require, exports, provide … with, uses y opens (cada uno de los cuales discutimos).

Como verá más adelante, la compilación de la declaración del módulo crea el descriptor del módulo, que se almacena en un archivo denominado module-info.class en la carpeta raíz del módulo. Aquí presentamos brevemente cada directiva de módulo. Después de eso, presentaremos las declaraciones reales del módulo.

Las palabras clave exports, module, open, opens, provides, requires, uses, with, as to transitive, que presentamos más adelante, son palabras clave restringidas. Son palabras clave solo en las declaraciones de los módulos y pueden usarse como identificadores en cualquier otro lugar de su código.

Una directiva de módulo requiere que este módulo dependa de otro módulo; esta relación se denomina dependencia de módulo. Cada módulo debe declarar explícitamente sus dependencias. Cuando el módulo A requiere el módulo B, se dice que el módulo A lee el módulo B y el módulo A lo lee el módulo B. Para especificar una dependencia en otro módulo, use requires, como en:

requires nombre de módulo;

También hay una directiva estática requiere para indicar que se requiere un módulo en tiempo de compilación, pero es opcional en tiempo de ejecución. Esto se conoce como una dependencia opcional y no se discutirá en esta introducción.

Para especificar una dependencia en otro módulo y para asegurar que otros módulos que leen su módulo también lean esa dependencia, conocida como lectura implícita, el uso requiere transitivo, como en:

requires nombre de módulo transitivo;

Considere la siguiente directiva de la declaración del módulo java.desktop:

requires transitivo java.xml;

En este caso, cualquier módulo que lea java.desktop también lee implícitamente java.xml. Por ejemplo, si un método del módulo java.desktop devuelve un tipo del módulo java.xml, el código de los módulos que leen java.desktop pasa a depender de java.xml.

Sin la directiva transitiva requerida en la declaración del módulo de java.desktop, dichos módulos dependientes no se compilarán a menos que lean explícitamente java.xml.

De acuerdo con JSR 379, los módulos estándar de Java SE deben otorgar legibilidad implícita en todos los casos como el descrito aquí. Además, aunque un módulo estándar Java SE puede depender de módulos no estándar, no debe otorgarles legibilidad implícita.

Esto garantiza que el código que depende únicamente de los módulos estándar de Java SE sea portátil en las implementaciones de Java SE.

Una directiva de módulo de exportación especifica uno de los paquetes del módulo cuyos tipos públicos (y sus tipos anidados públicos y protegidos) deberían ser accesibles para codificar en todos los demás módulos.

Una directiva Exportar … a directivas le permite especificar con precisión en una lista separada por comas qué código de módulos o módulos puede acceder al paquete exportado; esto se conoce como exportación calificada.

Una directiva de módulo de usos especifica un servicio utilizado por este módulo, por lo que el módulo es un consumidor de servicios. Un servicio es un objeto de una clase que implementa la interfaz o amplía la clase abstracta especificada en la directiva de usos.

El proporciona parte de la directiva especifica una interfaz o clase abstracta enumerada en la directiva de usos de un módulo y con parte de la directiva especifica el nombre de la clase de proveedor de servicios que implementa la interfaz o amplía la clase abstracta.

Una motivación clave del sistema de módulos es una fuerte encapsulación. Por defecto, un tipo en un módulo no es accesible para otros módulos a menos que sea un tipo público y usted exporte su paquete. Usted expone solo los paquetes que desea exponer. Con Java 9, esto también se aplica a la reflexión.

Permitir acceso solo en tiempo de ejecución a un paquete. Una directiva de módulo de apertura del formulario

open the package

indica que los tipos públicos de un paquete específico (y sus tipos públicos y protegidos anidados) son accesibles para el código en otros módulos solo en tiempo de ejecución. Además, todos los tipos en el paquete especificado (y todos los miembros de los tipos) son accesibles a través de la reflexión.

 

Permitir acceso solo en tiempo de ejecución a todos los paquetes en un módulo. Si todos los paquetes en un módulo dado deben ser accesibles en tiempo de ejecución y por reflexión a todos los demás módulos, puede abrir todo el módulo, como en:

módulo abierto modulename {
// directivas del módulo
}

Valores predeterminados de reflexión

De forma predeterminada, un módulo con acceso reflexivo en tiempo de ejecución a un paquete puede ver los tipos públicos del paquete (y sus tipos públicos y protegidos anidados).

Sin embargo, el código en otros módulos puede acceder a todos los tipos en el paquete expuesto y a todos los miembros de esos tipos, incluidos los miembros privados a través de setAccessible, como en las versiones anteriores de Java.

Para obtener más información sobre setAccessible y la reflexión, consulte la documentación de Oracle.

 

Compártelo

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *