Programmering

Modularitet i Java 9: ​​Stables opp med Project Jigsaw, Penrose og OSGi

Denne artikkelen gir en oversikt over forslag, spesifikasjoner og plattformer som tar sikte på å gjøre Java-teknologi mer modulær i Java 9. Jeg vil diskutere faktorer som bidrar til behovet for en mer modulær Java-arkitektur, kort beskrive og sammenligne løsningene som er foreslått, og introdusere de tre modularitetsoppdateringene som er planlagt for Java 9, inkludert deres potensielle innvirkning på Java-utvikling.

Hvorfor trenger vi Java-modularitet?

Modularitet er et generelt begrep. I programvare gjelder det å skrive og implementere et program eller datasystem som et antall unike moduler, snarere enn som en enkelt monolitisk design. Et standardisert grensesnitt brukes deretter for å gjøre det mulig for modulene å kommunisere. Partisjonering av et miljø med programvarekonstruksjoner i forskjellige moduler hjelper oss med å minimere kobling, optimalisere applikasjonsutvikling og redusere systemkompleksiteten.

Modularitet gjør det mulig for programmerere å gjøre funksjonstesting isolert og delta i parallelle utviklingsarbeid under en gitt sprint eller et prosjekt. Dette øker effektiviteten gjennom hele livssyklusen for programvareutvikling.

Noen karakteristiske attributter til en ekte modul er:

  • En selvstendig distribusjonsenhet (løs kobling)
  • En jevn og unik identitet (modul-ID og versjon)
  • Enkelt identifiserte og oppdagede krav og avhengigheter (standard kompileringstid og distribusjonsanlegg og metainformasjon)
  • Et åpent og forståelig grensesnitt (kommunikasjonskontrakt)
  • Skjulte implementeringsdetaljer (innkapsling)

Systemer som er bygget for å behandle moduler effektivt, bør gjøre følgende:

  • Støtte modularitet og avhengighetsfunn ved kompileringstid
  • Utfør moduler i et kjøretidsmiljø som støtter enkel distribusjon og omplassering uten systemnedetid
  • Implementere en eksekvering livssyklus som er klar og robust
  • Gi fasiliteter for enkel registrering og oppdagelse av moduler

Objektorienterte, komponentorienterte og serviceorienterte løsninger har alle forsøkt å muliggjøre ren modularitet. Hver løsning har sitt eget sett med særegenheter som forhindrer at den oppnår modulær perfeksjon. La oss vurdere det kort.

Java-klasser og objekter som modulkonstruksjoner

Oppfyller ikke den objektorienterte naturen til Java kravene til modularitet? Tross alt, objektorientert programmering med Java understreker og noen ganger håndhever unikhet, datakapsling og løs kobling. Selv om disse punktene er en god start, legg merke til modulkravene som ikke er det møtt av Javas objektorienterte rammeverk: identitet på objektnivå er upålitelig; grensesnitt er ikke versjonert: og klasser er ikke unike på distribusjonsnivå. Løs kobling er en god praksis, men absolutt ikke håndheves.

Gjenbruk av klasser i Java er vanskelig når tredjepartsavhengigheter misbrukes så lett. Kompileringstidsverktøy som Maven søker å løse denne mangelen. Faktisk språkkonvensjoner og konstruksjoner som avhengighetsinjeksjon og inversjon av kontroll hjelper utviklere i vårt forsøk på å kontrollere kjøretidsmiljøet, og noen ganger lykkes de, spesielt hvis de brukes med streng disiplin. Dessverre etterlater denne situasjonen arbeidet med å skape et modulært miljø opp til proprietære rammekonvensjoner og konfigurasjoner.

Java legger også til pakkenavnområder og omfangssynlighet til blandingen som et middel for å lage modulære kompileringstider og distribusjonstidsmekanismer. Men disse språkfunksjonene blir lett fjernet, som jeg skal forklare.

Pakker som en modulær løsning

Pakker prøver å legge til et abstraksjonsnivå i Java-programmeringslandskapet. De gir fasiliteter for unike kodingsnavnområder og konfigurasjonskontekster. Dessverre er det imidlertid lett å omgå pakkekonvensjoner, noe som ofte fører til et miljø med farlige kompileringskoblinger.

Modularitetstilstanden i Java for øyeblikket (bortsett fra OSGi, som jeg vil diskutere om kort tid) oppnås oftest ved hjelp av pakkenavnområder, JavaBeans-konvensjoner og proprietære rammekonfigurasjoner som de som ble funnet på våren.

Er ikke JAR-filer modulære nok?

JAR-filer og distribusjonsmiljøet de opererer i forbedrer i stor grad de mange eldre distribusjonskonvensjonene som ellers er tilgjengelige. Men JAR-filer har ingen egenart, bortsett fra et sjelden brukt versjonsnummer, som er skjult i et .jar-manifest. JAR-filen og det valgfrie manifestet brukes ikke som modularitetskonvensjoner i Java-kjøretidsmiljøet. Så pakkenavnene til klasser i filen og deres deltakelse i en klassesti er de eneste delene av JAR-strukturen som gir moduler til kjøretidsmiljøet.

Kort sagt, JAR er et godt forsøk på modulering, men de oppfyller ikke alle kravene for et virkelig modulært miljø. Rammeverk og plattformer som Spring og OSGi bruker mønstre og forbedringer av JAR-spesifikasjonen for å gi miljøer for å bygge veldig dyktige og modulære systemer. Over tid vil imidlertid selv disse verktøyene bukke under for en veldig uheldig bivirkning av JAR-spesifikasjonen JAR helvete!

Classpath / JAR helvete

Når Java runtime-miljøet tillater vilkårlig komplekse JAR-lastemekanismer, vet utviklere at de er i klassesti helvete eller JAR helvete. En rekke konfigurasjoner kan føre til denne tilstanden.

Først bør du vurdere en situasjon der en Java-applikasjonsutvikler gir en oppdatert versjon av applikasjonen og har pakket den i en JAR-fil med nøyaktig samme navn som den gamle versjonen. Java kjøretidsmiljø gir ingen valideringsfasiliteter for å bestemme riktig JAR-fil. Kjøretidsmiljøet laster ganske enkelt inn klasser fra JAR-filen som den finner først eller som tilfredsstiller en av mange klassestieregler. Dette fører i beste fall til uventet oppførsel.

En annen forekomst av JAR-helvete oppstår der to eller flere applikasjoner eller prosesser avhenger av forskjellige versjoner av et tredjepartsbibliotek. Ved bruk av standard klasselastingsanlegg vil bare en versjon av tredjepartsbiblioteket være tilgjengelig under kjøretid, noe som fører til feil i minst en applikasjon eller prosess.

Et fullverdig og effektivt Java-modulsystem skal gjøre det lettere å skille kode i forskjellige, lett forståelige og løst koblede moduler. Avhengighet bør være tydelig spesifisert og strengt håndhevet. Fasiliteter bør være tilgjengelige som gjør det mulig å oppgradere moduler uten å ha en negativ effekt på andre moduler. Et modulært kjøretidsmiljø bør muliggjøre konfigurasjoner som er spesifikke for et bestemt domene eller vertikalt marked, og dermed redusere oppstartstiden og systemets fotavtrykk.

Modularitetsløsninger for Java

Sammen med modularitetsfunksjonene som er nevnt så langt, legger den siste innsatsen til noen flere. Følgende funksjoner er ment for å optimalisere ytelsen og muliggjøre utvidelse av kjøretidsmiljøet:

  • Segmentert kildekode: Kildekode delt inn i forskjellige, bufret segmenter, som hver inneholder en bestemt type kompilert kode. Målene inkluderer å hoppe over ikke-metoden kode under søppel feiring, trinnvis bygge, og bedre minnehåndtering.
  • Bygghåndhevelser: Språk konstruerer for å håndheve navneområder, versjonering, avhengigheter og andre.
  • Implementeringsanlegg: Støtte for å distribuere skalerte kjøretidsmiljøer i henhold til spesifikke behov, for eksempel de i et mobilt enhetsmiljø.

En rekke modularitetsspesifikasjoner og rammer har søkt å lette disse funksjonene, og noen få har nylig steget til topps i forslag til Java 9. En oversikt over Java-modularitetsforslag er nedenfor.

JSR (Java Specification Request) 277

For tiden inaktiv er Java Specification Request (JSR) 277, Java Module System; introdusert av Sun i juni 2005. Denne spesifikasjonen dekket de fleste av de samme områdene som OSGi. I likhet med OSGi definerer JSR 277 også oppdagelse, lasting og konsistens av moduler, med sparsom støtte for kjøretidsmodifikasjoner og / eller integritetskontroll.

Ulempene med JSR 277 inkluderer:

  • Ingen dynamisk lasting og lossing av moduler / bunter
  • Ingen kjøretidskontroller for klasseplassens unikhet

OSGi (Open Service Gateway Initiative)

OSGI-plattformen ble introdusert av OSGI Alliance i november 1998, og er det mest brukte modularitetssvaret på det formelle standardspørsmålet for Java. For øyeblikket ved utgivelse 6 er OSGi-spesifikasjonen allment akseptert og brukt, spesielt sent.

I hovedsak er OSGi et modulært system og en tjenesteplattform for Java-programmeringsspråket som implementerer en komplett og dynamisk komponentmodell i form av moduler, tjenester, distribuerbare pakker og så videre.

De primære lagene i OSGI-arkitekturen er som følger:

  • Utførelsesmiljø: Java-miljøet (for eksempel Java EE eller Java SE) som en pakke vil kjøre under.
  • Modul: Hvor OSGi-rammeverket behandler de modulære aspektene av en pakke. Bundle metadata behandles her.
  • Livssyklus: Initialisering, start og stopp av bunter skjer her.
  • Tjeneste register: Hvor pakker viser tjenestene deres for andre pakker å oppdage.

En av de største ulempene med OSGi er mangelen på en formell mekanisme for installering av innfødte pakker.

JSR 291

JSR 291 er et dynamisk komponent-rammeverk for Java SE som er basert på OSGi, og er for tiden i siste fase av utviklingen. Denne innsatsen fokuserer på å ta OSGi inn i vanlig Java, slik det ble gjort for Java-mobile miljøet av JSR 232.

JSR 294

JSR 294 definerer et system av metamoduler og delegerer den faktiske utførelsen av pluggbare moduler (versjoner, avhengigheter, begrensninger osv.) Til eksterne leverandører. Denne spesifikasjonen introduserer språkutvidelser, for eksempel "superpakker" og hierarkisk relaterte moduler, for å lette modularitet. Streng innkapsling og distinkte kompilasjonsenheter er også en del av spesifikasjonens fokus. JSR 294 er for øyeblikket sovende.

Project Jigsaw

Project Jigsaw er den mest sannsynlige kandidaten for modularitet i Java 9. Jigsaw søker å bruke språkkonstruksjoner og miljøkonfigurasjoner for å definere et skalerbart modulsystem for Java SE. Hovedmålene til Jigsaw inkluderer:

  • Gjør det veldig enkelt å skalere Java SE-kjøretiden og JDK ned til små enheter.
  • Forbedre sikkerheten til Java SE og JDK ved å forby tilgang til interne JDK APIer og ved å håndheve og forbedre SecurityManager.checkPackageAccess metode.
  • Forbedring av applikasjonsytelsen via optimalisering av eksisterende kode og tilrettelegging for fremtidsrettede programoptimaliseringsteknikker.
  • Forenkling av applikasjonsutvikling i Java SE ved at biblioteker og applikasjoner kan bygges fra utviklermoduler og fra en modulær JDK
  • Krever og håndhever et endelig sett med versjonsbegrensninger

JEP (Java Enhancement Proposal) 200

Java Enhancement Proposal 200 opprettet i juli 2014, søker å definere en modulstruktur for JDK. JEP 200 bygger på Jigsaw-rammeverket for å gjøre det lettere å segmentere JDK, ifølge Java 8 Compact Profiles, i sett med moduler som kan kombineres ved kompileringstid, byggetid og distribusjonstid. Disse kombinasjonene av moduler kan deretter distribueres som nedskalerte kjøretidsmiljøer som består av Jigsaw-kompatible moduler.

JEP 201

JEP 201 søker å bygge videre på Jigsaw for å omorganisere JDK-kildekoden i moduler. Disse modulene kan deretter kompileres som forskjellige enheter av et forbedret byggesystem som håndhever modulgrensene. JEP 201 foreslår en kildekodestruktureringsordning i hele JDK som legger vekt på modulgrenser på det øverste nivået av kildekodetrær.

Penrose

Penrose ville håndtere interoperabilitet mellom Jigsaw og OSGi. Spesielt vil det legge til rette for muligheten til å endre OSGi-mikrokjerner for at bunter som kjører i den modifiserte kjernen, skal bruke Jigsaw-moduler. Det er avhengig av å bruke JSON for å beskrive moduler.

Planer for Java 9

Java 9 er en unik hovedutgivelse for Java. Det som gjør det unikt, er introduksjonen av modulære komponenter og segmenter gjennom hele JDK. De viktigste funksjonene som støtter modularisering er:

  • Modulær kildekode: I Java 9 vil JRE og JDK omorganiseres til interoperable moduler. Dette vil muliggjøre opprettelse av skalerbare kjøretider som kan kjøres på små enheter.
  • Segmentert kodebuffer: Selv om det ikke er et modulært anlegg, vil den nye segmenterte kodebufferen til Java 9 følge modulariseringens ånd og nyte noen av de samme fordelene. Den nye kodebufferen vil ta intelligente beslutninger om å kompilere kodesegmenter som ofte er tilgjengelige, til naturlig kode og lagre dem for optimal oppslag og fremtidig utførelse. Bunken vil også bli segmentert i 3 forskjellige enheter: kode som ikke er metode som lagres permanent i hurtigbufferen; kode som har en potensielt lang livssyklus (kjent som "ikke-profilert kode"); og kode som er forbigående (kjent som "profilert kode").
  • Bygghåndhevelser: Byggesystemet vil bli forbedret, via JEP 201, for å kompilere og håndheve modulgrenser.
  • Implementeringsanlegg: Verktøy vil bli gitt innen Jigsaw-prosjektet som vil støtte modulgrenser, begrensninger og avhengigheter ved distribusjonstidspunktet.

Utgivelse av Java 9 for tidlig tilgang

Mens den eksakte utgivelsesdatoen til Java 9 fortsatt er et mysterium, kan du laste ned en tidlig tilgangsutgivelse på Java.net.

For å konkludere

Denne artikkelen har vært en oversikt over modularitet innenfor Java-plattformen, inkludert muligheter for modularitet i Java 9. Jeg forklarte hvordan mangeårige problemer som classpath helvete bidrar til behovet for en mer modulær Java-arkitektur og diskuterte noen av de nyeste nye modularitetene funksjoner som er foreslått for Java. Deretter beskrev jeg og kontekstualiserte hvert av Java-modularitetsforslagene eller plattformene, inkludert OSGi og Project Jigsaw.

Behovet for en mer modulær Java-arkitektur er tydelig. Nåværende forsøk har kommet til kort, selv om OSGi kommer veldig nært. For Java 9-utgivelsen vil Project Jigsaw og OSGi være hovedaktørene i modulområdet for Java, med Penrose som muligens gir limet mellom dem.

Denne historien, "Modularity in Java 9: ​​Stacking up with Project Jigsaw, Penrose, and OSGi" ble opprinnelig utgitt av JavaWorld.

$config[zx-auto] not found$config[zx-overlay] not found