A partire dalla versione 9, la politica di Oracle è stata quella di rilasciare gli aggiornamenti di Java con una cadenza semestrale.
Il rilascio delle nuove versioni viene pianificato per i mesi di marzo e settembre
di ogni anno. Con il presente articolo introduciamo la release 11 offerta da Oracle
a partire dal mese di Settembre 2018.
Nuove funzionalità di Java 11
Il primo aspetto da sottolineare
riguarda la tipologia di release che Java 11 rappresenta, si tratta infatti di una LTS
(Long-Term Support), ciò indica la possibilità di ricevere aggiornamenti per un periodo
di almeno otto anni. La licenza LTS offre
aggiornamenti con performance, stabilità e sicurezza certificati e garantiti direttamente
da Oracle. Gli utenti che invece intendono
avere un continuo accesso alle nuove migliorie, possono orientarsi sui rilasci delle versioni di tipo
OpenJDK.
Oracle fornirà le versione della JDK sia attraverso licenza GNU GPL v2
con la Classpath Exception (GPLv2+CPE) che commerciale per l'utilizzo delle JDK
come parte di un prodotto o servizio di Oracle. Questa combinazione,
Open Source + Commerciale va a sostituire la storica BCL. Le JDK sotto BCL
non contenevano in genere caratteristiche presenti nelle commerciali, la modifica
determina quindi che le versione JDK di Oracle e le
OpenJDK saranno essenzialmente analoghe e nella versione Open
avremo:
- ZGC: Scalable Low-Latency Garbage Collector.
- Lazy Allocation of Compiler Threads.
- Epsilon GC.
ZGC: Scalable Low-Latency Garbage Collector
ZGC è la sigla che indica lo Z Garbage Collector, un garbage collector scalabile a bassa latenza progettato per raggiungere
un tempo di attesa non superiore ai 10 ms e per la gestione di una memoria HEAP che va dalle centinaia di Mb
a diversi Tb. Lo ZGC è un garbage collector concorrente, questo significa che il grosso del suo lavoro viene
effettuato con i threads Java che continuano la loro esecuzione.
Tale comportamento limita notevolmente l'impatto negativo che la grabage collection può avere sui tempi di risposta delle applicazioni.
Lazy Allocation of Compiler Threads
L'allocazione Lazy ("pigra") dei thread di compilazione permette di gestire dinamicamente l'allocazione di thread
fronteggiando il comportamento di default della VM caratterizzato dalla creazione di un elevato numero di processi su sistemi
con diverse CPUs, indipendentemente dalla memoria disponibile e dal numero di richieste di compilazione. La gestione
Lazy è resa possibile da nuovo comando:
-XX:+UseDynamicNumberOfCompilerThreads
Epsilon GC
Epsilon GC è un Garbage Collector no-op sperimentale, gestisce soltanto l'allocazione di memoria non implementando
alcun meccanismo di recupero della stessa. Il suo utilizzo è particolarmente utile per effettuare test di performance
al fine di valutare costi e benefici di differenti implementazioni del Garbage Collectors o, in casi estremi, per l'utilizzo
con Job di vita particolarmente breve dove la fase di recupero della memoria coincide con la terminazione della JVM.
Modifiche al linguaggio Java
Le modifiche che riguardano direttamente il linguaggio vanno a migliorare e completare aspetti già introdotti
dalla versione 10. Ad esempio con Java 10 l'introduzione della parola chiave var
ha inserito nel linguaggio l'inferenza automatica del tipo portando alla scrittura di un codice più compatto. Nel seguente frammento di codice
var mioTesto = "Ciao Java 11";
il compilatore deduce il tipo della variabile sulla base del valore assegnato, in questo caso una stringa. La limitazione
di Java 10 impediva il suo utilizzo all'interno di espressioni Lambda ed è stata rimossa portando benefici non
tanto in termini di un codice meno verboso, quanto per la possibilità di utilizzare annotazioni per i parametri di una
Lambda expression:
Predicate<String> mioPredicato = (@Nullable var myVar) -> true;
Con Java 9 abbiamo visto l'introduzione delle HttpClient API come incubating feature, Java 11
completa queste API rendendole disponibili nel package java.net
. La classe Stream
viene fornita di tre nuovi metodi:
ofNullable()
, che consente di ottenere uno stream da un singolo elemento, e dropWhile()
e takeWhile()
che possono ricevere un predicato per determinare quali elementi abbandonare di un stream:
Stream.ofNullable(null).count();
Stream.of(1, 2, 3).dropWhile(n -> n < 2).collect(Collectors.toList());
Stream.of(1, 2, 3).takeWhile(n -> n < 2).collect(Collectors.toList());
Molto interessanti sono infine i metodi che arricchiscono la classe String
e che consentono un facile test su stringhe vuote,
eliminazione di spazio ad inizio o fine stringa e conteggio di linee:
" ".isBlank(); // true
" Testo1 Testo2 ".strip(); // "Testo1 Testo2"
" Testo1 Testo2 ".stripTrailing(); // " Testo1 Testo2"
" Testo1 Testo2 ".stripLeading(); // "Testo1 Testo2 "
"Testo1".repeat(3); // "Testo1Testo1Testo1"
"Testo1\nTesto1\nTesto1".lines().count(); // 3