středa 28. března 2007

Java Module System

Pro Javu 7 se chystá vylepšení v oblasti nasazení (deploymentu) aplikací z hlediska modularity, verzovatelnosti a správy. To byla ta příznivější část sdělení, ta druhá méně potěšitelná je, že to zatím nevypadá na kompatibilní řešení se specifikací OSGi - The Dynamic Module System for Java, na kterém stojí například produkty z rodiny Eclipse nástrojů. Všechno nasvědčuje tomu, že se schyluje k další "válce".

Java Module System je pokryté v JSR-277 a zároveň k němu patří JSR 294 standardizující takzvané superpackage. Pokud proběhne specifikace obou požadavků do finálního stavu, měly by se stát součástí Javy 7.

Nasazení (deployment) aplikací v Jave je svázán s konceptem JAR balíků, pocházejícíh z ranných dob platformy. Modulárnost aplikací, či jednotlivých komponent se na úrovni balení (packageování) rozlišuje pomocí JAR balíků (vynechme speciální příklad enterprise oblasti). Aplikace A balená do souboru a.jar může například záviset na komponentě B balené do souboru b.jar. Neexistuje žádný standardní způsob jak pro JVM vyjádřit:

  • A závisí na B
  • B musí být ve verzy X.Y.Z
  • zjistit jestli B nezávisí na další komponentě
  • pokud B není k dispozici na classpath, kde jej st8hnout

Právě z tohoto důvou definuje JSR-277 následující čtyři klíčové komponenty.

  • modul
  • verzovací schéma
  • repository modulů
  • podpora na úrovni JVM (kontrola, vyhledávání, nahrávání)

Modul

modul - minimálni jednotka granularity. Obsahuje třídy, metadata a případně další resources (obrázky, properties soubory apod.). Metadata definují jméno modulu a verzi, závislosti na jiných modulech, viditelnost tříd (superpackage) a obsah všech tříd a resourců.

Metadata leží v souboru METADATA.module jehož obsah může vypadat následovně.


@Version(“1.0.0”)
super package com.sun.cool.library { // module name
  // exported class(es)
  export com.sun.cool.library.ClassA;
  export com.sun.cool.library.InterfaceB;
  // module membership
  com.sun.cool.library.ClassA;
  com.sun.cool.library.InterfaceB;
  com.sun.cool.library.PrivateClassC;
  com.sun.cool.library.abc.moreStuff;
  // no import
}  
  
Superpackage

Exported classes je průnik se superpackegem definovaným v JSR 294. Superpackege přidává jemnější rozlišení co do viditelnosti jednotlivých tříd mezi moduly na úrovni package.

Například máme třídy v package org.framework.api a třídy v package org.framework.api.internal. Aby na třídy z interního package bylo vidět v org.framework.api, musí být deklarovány jako public. Díky tomu se ovšem dostávájí do globální viditelnosti.

Díky definici superpackage v rámci modulu mohu říci, že pouze třídy org.framework.api jsou exportované do globální viditelnosti. Tedy kdokoliv si je může importovat a pracovat s nimi. Pokud by třída mimo superpackage zkusila importovat třídu org.framework.api.internal, skončila by stejně jako jakákoliv třída, která se dnes snaží importovat package private třídu.

Superpackage bude možné definovat i mimo moduly a to přímo v JAR souborech. Obě specifikace (277 i 294) zatím definují jiný formát pro exportování tříd. Zatím tedy není jasné jaký formát bude zvolen jako finalní. Osobně mi přijde, že vztah obou specifikací je zatím hodně volný, proto doporučuji přečíst článek Andrease Sterbenze Superpackages in JSR 294, kde je dobré Q&A.

Zpět k modulům. Celý modul je zabalen do souboru s jmennou konvencí <name>-<version>[-<platform>-<arch>].jam . Mimochodem přípona JAM znamená Java Modul, takže budeme jamovat. Struktura souboru může vypadat následovně.


org.foo.complex-1.0.0.jam:
  /META-INF/MANIFEST.MF
  /MODULE-INF
    METADATA.module
    bin/windows/x86/bar.dll
    bin/linux/x86/bar.so
    bin/solaris/x86/bar.so
    bin/solaris/sparc/bar.so
    lib/javahelp-1.2.0.jar
  /org/foo/complex/ComplexApp.class
  /icons/drawing.jpg

Do podobných modulů by měla být verzovaná i Java. Takže budeme mít například standard edition modul, exportující všechny třídy z package java.* a javax.*. Modul závislý na Jave 7 a vyšší, pak bude moci deklarovat závislost v metadatech // ImportModule(java.se, @VersionConstraint("1.7+"))

Verzovací schéma

Verzovací schéma (major[.minor[.micro[.update]]][-qualifier]) umožňuje popsat verzi modulu. Modul stejného jména, ale jiné revize představuje z pohledu systému jiný modul. Moduly různé verze mohou koeexistovat v rámci jedné JVM. Další zajímavostí verzovacího schématu je, že definuje konvenci (nebude kontrolovaná JVM) pro upgrade verze vyhledem k změnám API. Například upgrade čísla na úrovni micro identifikátoru znamená, že se nemění zpětná kompatibilita.

Repository modulů

Reposiotry modulů umožňuje jejich ukládání, vyhledávání a získávání. Struktura jednotlivých repository může být stromová s delegací na nadřízenou repository. Repository nemusí být nutně lokální, ale může běžet někde na síti. Díky tomu je možné mít jednu centrálně spravovanou repository pro celeou organizaci, z které čerpají všechny používané java aplikace.

Repository může dělat úlohy jako verifikaci bytecode, kontrolu digitálního podpisu a další. JVM může jednotlivé moduly díky repository nahrávat až když je opravdu potřebuje. Repository by měla být definována abstraktně, aby bylo možné vytvářet její specializované implementace, například založené na databázi.

Podpora na úrovni JVM

No a somozřejmě všechny vymoženosti Java Module System bude na plno využívat JVM. Z repository bude nahrávat potřebné moduly, classloading bude upravený tak, aby vedle sebe mohly existovat stejné moduly v rozdílných revizích. JVM bude rovněž kontrolovat přístup k superpackagům a ohlídá, že všechny závislosti jsou k dispozici.

Závěr

O kompatibilitě či spíš nekompatibilitě s OSGi jsem již mluvil na začátku. Pokud Vás zajímá srovnání s OSGi, tak si přečtěte přímo review JSR 277 na stránkách OSGi, je to zajímavé počtení. Co JSR 277 chybí a na co poukazuje zmíněný článek, je opomenutá dynamická zpráva modulů za běhu (deploy, undeploy, redeploy).

Poznámka: JSR 277 je zatím ve stavu early draftu, všechny informace z tohoto článku se k této verzi specifikace vztahují. V budoucnu je tedy možné, že některá z informací nebude platit.

Zdroje