JDK 16: le nuove funzionalità di Java 16

Java Development Kit (JDK) 16 ha raggiunto la sua fase iniziale di rampdown, il che significa che il set di funzionalità è ora congelato, a partire dal 10 dicembre 2020. Le nuove funzionalità in JDK 16 vanno da una seconda anteprima di classi sigillate a pattern matching a thread simultanei. elaborazione dello stack per la raccolta dei rifiuti.

JDK 16 sarà l'implementazione di riferimento della versione di Java standard impostata per seguire JDK 15, che è arrivata il 15 settembre. Un programma di rilascio proposto prevede che JDK 16 raggiunga una seconda fase di rampdown il 14 gennaio 2021, seguita da release candidate in arrivo il 4 febbraio e 18 febbraio 2021. La pubblicazione della versione di produzione è prevista per il 16 marzo 2021.

Diciassette proposte hanno ufficialmente come target JDK 16 a partire dal 10 dicembre 2020. Le nuove funzionalità in arrivo in Java 16 includono:

  • La proposta di avvisi per classi basate sul valore designa le classi wrapper primitive come basate sul valore e depreca i loro costruttori per la rimozione, richiedendo nuovi avvisi di deprecazione. Vengono forniti avvisi sui tentativi impropri di sincronizzazione sulle istanze di qualsiasi classe basata sui valori nella piattaforma Java. A guidare questo sforzo è il Valhalla Project, che sta perseguendo un significativo miglioramento del modello di programmazione Java sotto forma di classi primitive. Le classi primitive dichiarano che le istanze sono prive di identità e capaci di rappresentazioni inline o appiattite, dove le istanze possono essere copiate liberamente tra le posizioni di memoria e codificate utilizzando i valori dei campi delle istanze.La progettazione e l'implementazione di classi primitive in Java è ora sufficientemente matura da poter anticipare la migrazione di alcune classi della piattaforma Java a classi primitive in una versione futura. I candidati alla migrazione sono designati in modo informale come classi basate sul valore nelle specifiche API.
  • Precedentemente visualizzate in anteprima in JDK 15, le classi e le interfacce sigillate limitano quali altre classi e interfacce possono estenderle o implementarle. Gli obiettivi del piano includono consentire all'autore di una classe o di un'interfaccia di controllare il codice responsabile della sua implementazione, fornire un modo più dichiarativo rispetto ai modificatori di accesso per limitare l'uso di una superclasse e supportare le direzioni future nella corrispondenza dei modelli fornendo una base per analisi dei modelli.
  • Forte incapsulamento degli interni JDK per impostazione predefinita, ad eccezione delle API interne critiche come misc.Unsafe. Gli utenti possono scegliere l'incapsulamento forte e rilassato che è stato l'impostazione predefinita da JDK 9. Gli obiettivi di questa proposta includono il miglioramento della sicurezza e della manutenibilità del JDK, come parte di Project Jigsaw, e l'incoraggiamento degli sviluppatori a migrare dall'utilizzo di elementi interni all'utilizzo di API standard in modo che sia gli sviluppatori che gli utenti finali possono aggiornare facilmente alle future versioni di Java. Questa proposta comporta il rischio principale che il codice Java esistente non venga eseguito. Gli sviluppatori sono incoraggiati a utilizzare lo strumento jdeps per identificare il codice che dipende dagli elementi interni del JDK e passare alle sostituzioni standard quando disponibili. Gli sviluppatori possono utilizzare una versione esistente, come JDK 11, per testare il codice esistente utilizzando --illegal-access=warnper identificare gli elementi interni a cui si accede tramite riflessione, utilizzando  --illegal-access=debugper individuare il codice errato e testare con --illegal-access=deny.
  • API linker esterno, che offre accesso Java puro di tipo statico al codice nativo. Questa API sarà in una fase di incubazione in JDK 16. Insieme all'API di accesso alla memoria esterna proposta, l'API del linker esterno semplificherà notevolmente il processo altrimenti soggetto a errori di associazione a una libreria nativa. Questo piano è inteso a sostituire JNI (Java Native Interface) con un modello di sviluppo Java puro superiore, per offrire supporto C e, nel tempo, per essere abbastanza flessibile da supportare il supporto per altre piattaforme, come x86 a 32 bit e funzioni straniere scritte in linguaggi diversi dal C, come C ++. Le prestazioni dovrebbero essere migliori o paragonabili a JNI.
  • Spostamento dell'elaborazione dello stack di thread ZGC (Z Garbage Collector) dai safepoint a una fase simultanea. Gli obiettivi di questo piano includono la rimozione dell'elaborazione dello stack di thread dai safepoint ZGC; rendere l'elaborazione dello stack pigra, cooperativa, concorrente e incrementale; rimuovere tutte le altre elaborazioni di root per thread dai safepoint ZGC; e fornendo un meccanismo per altri sottosistemi HotSpot VM per elaborare pigramente stack. ZGC ha lo scopo di rendere le pause GC e i problemi di scalabilità in HotSpot un ricordo del passato. Finora, le operazioni GC che scala con la dimensione dell'heap e la dimensione del metaspace sono state spostate dalle operazioni safepoint e nelle fasi simultanee. Questi hanno incluso la marcatura, il riposizionamento, l'elaborazione dei riferimenti, lo scaricamento delle classi e la maggior parte dell'elaborazione di root.Le uniche attività ancora svolte nei safepoint GC sono un sottoinsieme dell'elaborazione di root e un'operazione di terminazione del contrassegno a tempo. Queste radici hanno incluso stack di thread Java e altre radici di thread, con queste radici problematiche perché scalano con il numero di thread. Per andare oltre la situazione attuale, l'elaborazione per thread, inclusa la scansione dello stack, deve essere spostata in una fase simultanea. Con questo piano, il costo del throughput della latenza migliorata dovrebbe essere insignificante e il tempo trascorso all'interno dei safepoint ZGC su macchine tipiche dovrebbe essere inferiore a un millisecondo.deve essere spostato in una fase simultanea. Con questo piano, il costo del throughput della latenza migliorata dovrebbe essere insignificante e il tempo trascorso all'interno dei safepoint ZGC su macchine tipiche dovrebbe essere inferiore a un millisecondo.deve essere spostato in una fase simultanea. Con questo piano, il costo del throughput della latenza migliorata dovrebbe essere insignificante e il tempo trascorso all'interno dei safepoint ZGC su macchine tipiche dovrebbe essere inferiore a un millisecondo.
  • Una capacità metaspace elastica, che restituisce più prontamente al sistema operativo la memoria dei metadati della classe HotSpot VM (metaspace) inutilizzata, riduce il footprint del metaspace e semplifica il codice del metaspace per ridurre i costi di manutenzione. Metaspace ha avuto problemi con un elevato utilizzo della memoria fuori heap. Il piano prevede la sostituzione dell'allocatore di memoria esistente con uno schema di allocazione basato su amici, fornendo un algoritmo per dividere la memoria in partizioni per soddisfare le richieste di memoria. Questo approccio è stato utilizzato in luoghi come il kernel Linux e renderà pratico allocare la memoria in blocchi più piccoli per ridurre il sovraccarico del caricatore di classi. Anche la frammentazione sarà ridotta. Inoltre, l'impegno della memoria dal sistema operativo alle arene di gestione della memoria sarà fatto pigramente, su richiesta,per ridurre l'ingombro per i caricatori che iniziano con grandi arene ma non li usano immediatamente o potrebbero non usarli completamente. Per sfruttare appieno l'elasticità offerta dall'allocazione dei compagni, la memoria del metaspazio sarà organizzata in granuli di dimensioni uniformi che possono essere impegnati e disimpegnati indipendentemente l'uno dall'altro.
  • Abilitazione delle funzionalità del linguaggio C ++ 14, per consentire l'uso delle funzionalità C ++ 14 nel codice sorgente JDK C ++ e fornire indicazioni specifiche su quali di queste funzionalità possono essere utilizzate nel codice HotSpot VM. Attraverso JDK 15, le funzionalità del linguaggio utilizzate dal codice C ++ in JDK sono state limitate agli standard del linguaggio C ++ 98/03. Con JDK 11, il codice sorgente è stato aggiornato per supportare la creazione con versioni più recenti dello standard C ++. Ciò include la possibilità di compilare con versioni recenti di compilatori che supportano le funzionalità del linguaggio C ++ 11/14. Questa proposta non propone modifiche allo stile o all'utilizzo del codice C ++ utilizzato al di fuori di HotSpot. Ma per sfruttare le funzionalità del linguaggio C ++, sono necessarie alcune modifiche in fase di compilazione, a seconda del compilatore della piattaforma.
  • Un'API vettoriale in una fase dell'incubatore, in cui il JDK sarebbe dotato di un modulo incubatore, jdk.incubator.vector, per esprimere calcoli vettoriali che si compilano in istruzioni hardware vettoriali ottimali sulle architetture CPU supportate, per ottenere prestazioni superiori a calcoli scalari equivalenti. L'API vettoriale fornisce un meccanismo per scrivere algoritmi vettoriali complessi in Java, utilizzando il supporto preesistente nella VM HotSpot per la vettorizzazione ma con un modello utente che rende la vettorizzazione più prevedibile e robusta. Gli obiettivi della proposta includono fornire un'API chiara e concisa per esprimere una gamma di calcoli vettoriali, essere indipendente dalla piattaforma supportando più architetture di CPU e offrire compilazioni e prestazioni di runtime affidabili su architetture x64 e AArch64. Anche il grazioso degrado è un obiettivo,in cui un calcolo vettoriale si degraderebbe con grazia e funzionerebbe ancora se non può essere espresso completamente in fase di esecuzione come una sequenza di istruzioni vettoriali hardware, perché un'architettura non supporta alcune istruzioni o un'altra architettura CPU non è supportata.
  • Porting del JDK sulla piattaforma Windows / AArch64. Con il rilascio del nuovo hardware AArch64 (ARM64) di classe server e consumer, Windows / AArch64 è diventato una piattaforma importante a causa della domanda. Sebbene il porting stesso sia già per lo più completo, l'obiettivo di questa proposta riguarda l'integrazione del port nel repository JDK della linea principale.
  • Porting del JDK su Alpine Linux e su altre distribuzioni Linux che utilizzano musl come libreria C primaria, su architetture x64 e AArch64. Musl è un'implementazione Linux della funzionalità della libreria standard descritta negli standard ISO C e Posix. Alpine Linux è ampiamente adottato nelle distribuzioni cloud, nei microservizi e negli ambienti container a causa delle dimensioni ridotte dell'immagine. Un'immagine Docker per Linux è più piccola di 6 MB. Lasciare che Java venga eseguito immediatamente in tali impostazioni consentirà a Tomcat, Jetty, Spring e altri framework popolari di funzionare in questi ambienti in modo nativo. Utilizzando jlink per ridurre le dimensioni del runtime Java, un utente può creare un'immagine ancora più piccola su misura per eseguire un'applicazione specifica.
  • Fornire classi di record che fungono da vettori trasparenti per dati immutabili. I record possono essere considerati tuple nominali. I record sono stati visualizzati in anteprima in JDK 14 e JDK 15. Questo sforzo è in risposta ai reclami secondo cui Java è stato troppo prolisso o ha troppe cerimonie. Gli obiettivi del piano includono l'ideazione di un costrutto orientato agli oggetti che esprima una semplice aggregazione di valori, aiutando gli sviluppatori a concentrarsi sulla modellazione di dati immutabili piuttosto che su comportamenti estensibili, implementando automaticamente metodi basati sui dati come equalse accessors e preservando principi Java di vecchia data come nominal digitando.
  • L'aggiunta di canali socket di dominio Unix, in cui il supporto socket di dominio Unix (AF_UNIX) viene aggiunto alle API del canale socket e del canale socket del server nel pacchetto nio.channels. Il piano estende anche il meccanismo del canale ereditato per supportare i canali socket del dominio Unix ei canali socket del server. I socket del dominio Unix vengono utilizzati per le comunicazioni tra processi sullo stesso host. Sono simili ai socket TCP / IP per molti aspetti tranne per il fatto che sono indirizzati da nomi di percorso del file system piuttosto che da indirizzi IP e numeri di porta. L'obiettivo della nuova funzionalità è supportare tutte le funzionalità dei canali socket di dominio Unix comuni alle principali piattaforme Unix e Windows. I canali socket del dominio Unix si comporteranno allo stesso modo dei canali TCP / IP esistenti in termini di comportamento di lettura / scrittura, configurazione della connessione, accettazione delle connessioni in entrata da parte dei server,e multiplexing con altri canali selezionabili non bloccanti in un selettore. I socket del dominio Unix sono più sicuri ed efficienti delle connessioni loopback TCP / IP per le comunicazioni locali tra processi.
  • Un'API di accesso alla memoria esterna, che consente ai programmi Java di accedere in modo sicuro alla memoria esterna all'esterno dell'heap Java. Precedentemente incubato in JDK 14 e JDK 15, l'API di accesso alla memoria esterna verrebbe nuovamente incubato in JDK 16, aggiungendo perfezionamenti. Sono state apportate modifiche, inclusa una più chiara separazione dei ruoli tra le interfacce MemorySegmente MemoryAddresses. Gli obiettivi di questa proposta includono la fornitura di una singola API per operare su vari tipi di memoria esterna, inclusa la memoria heap nativa, persistente e gestita. L'API non dovrebbe compromettere la sicurezza della JVM. Motivare la proposta è che molti programmi Java accedono alla memoria esterna, come Ignite, Memcached e MapDB. Ma l'API Java non fornisce una soluzione soddisfacente per l'accesso alla memoria esterna.
  • Il pattern matching per l' instanceofoperatore, anch'esso previsto in JDK 14 e JDK 15. Sarebbe stato finalizzato in JDK 16. Il pattern matching consente di esprimere in modo più conciso la logica comune in un programma, ovvero l'estrazione condizionale di componenti da oggetti in modo sicuro.
  • Fornire lo strumento jpackage per impacchettare applicazioni Java autonome. Introdotto come strumento di incubazione in JDK 14, jpackage è rimasto in incubazione in JDK 15. Con JDK 16, jpackage passa alla produzione, supportando formati di pacchetto nativi per offrire agli utenti un'esperienza di installazione naturale e consentire di specificare i parametri del momento del lancio al momento del confezionamento. I formati includono msi ed exe su Windows, pkg e dmg su MacOS e deb e rpm su Linux. Lo strumento può essere richiamato direttamente dalla riga di comando o in modo programmatico. Il nuovo strumento di pacchettizzazione affronta una situazione in cui molte applicazioni Java devono essere installate su piattaforme native in un modo di prima classe, piuttosto che essere collocate sul percorso di classe o sul percorso del modulo. È necessario un pacchetto installabile adatto alla piattaforma nativa.
  • Migrazione dei repository di codice sorgente OpenJDK da Mercurial a Git. A guidare questo sforzo sono i vantaggi nella dimensione dei metadati del sistema di controllo della versione e negli strumenti disponibili e nell'hosting.
  • Migrazione a GitHub, relativa alla migrazione da Mercurial a Git, con i repository di codice sorgente JDK 16 sul popolare sito di code-sharing. I rilasci delle funzioni JDK e gli aggiornamenti JDK per Java 11 e versioni successive faranno parte di questo piano. La transizione a Git, GitHub e Skara per Mercurial JDK e JDK-sandbox è stata eseguita il 5 settembre ed è aperta ai contributi.  

Le build ad accesso anticipato di JDK 16 per Linux, Windows e MacOS possono essere trovate su jdk.java.net. Come JDK 15, JDK 16 sarà una versione a breve termine, supportata per sei mesi. JDK 17, previsto per settembre 2021, sarà una versione con supporto a lungo termine (LTS) che riceverà diversi anni di supporto. L'attuale versione di LTS, JDK 11, è stata rilasciata a settembre 2018.