A próxima versão do Java SE, JDK 12, alcançou o primeiro ponto de desaceleração nas mudanças, em que algumas funcionalidades foram congeladas. Entre outras coisas, o JDK 12 fornece uma versão prévia da melhoria na declaração do Switch, aperfeiçoou o G1 e introduz o novo Garbage Collector chamado Shenandoah.
Uma das maiores propostas que é sobre literais string puras foi removidas do JDK 12. De acordo com a JEP, "Uma literal string pura pode ter muitas linhas de código sem a necessidade de caracteres de escape como o \n, ou na forma Unicode \uXXXX". Então ao invés de escrever:
String html = "<html>\n" +
" <body>\n" +
" <p>Hello World.</p>\n" +
" </body>\n" +
“</html>\n";
Posso escrever:
String html = `<html>
<body>
<p>Hello World.</p>
</body>
</html>
`;
"... achamos que deixá-lo no preview da versão atual não seria bom para a linguagem", escreveu Brian Goetz no email que explicou a decisão:
É claro que estamos decepcionados pelo fato de que levará mais tempo para que esse recurso entre na linguagem, mas achamos que essa é a melhor escolha.
Embora possamos esperar para que haja um bom volume de feedback, isso para qualquer recurso da linguagem, "Teria preferido de forma diferente". Ao revisar o feedback que recebemos, não estou mais convencido de que ainda temos o conjunto certo de compensações entre complexidade e expressividade, ou que exploramos o espaço de design o suficiente para ter certeza de que o design atual é o melhor que podemos fazer. Ao retirar do JDK 12, podemos continuar a refinar o design, explorar mais opções e apontar para um preview que realmente atenda aos requisitos do processo de Preview Feature (JEP 12).
Em termos de novos recursos de linguagem, foi adicionado no JDK 12 a JEP 325: Switch Expressions. Existem duas mudanças principais para serem feitas no Java com esta JEP. A primeira é uma nova forma de rótulo de switch, escrito "case L ->" para significar que somente o código à direita do valor deve ser executado se o valor for correspondido:
switch (day) {
case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);
case TUESDAY -> System.out.println(7);
case THURSDAY, SATURDAY -> System.out.println(8);
case WEDNESDAY -> System.out.println(9);
}
A segunda mudança é que o switch pode ser uma expressão, portanto, pode ter um valor ou retornar um valor:
T result = switch (arg) {
case L1 -> e1;
case L2 -> e2;
default -> e3;
};
O JDK 12 também fez algumas melhorias significativas no garbage collector G1. Um dos objetivos do G1 é atender a uma meta de tempo de pausa fornecida pelo usuário para suas coletas, no entanto, em determinadas circunstâncias, o coletor não consegue atingir essa meta. Isso acontece porque o G1 usa um conjunto de heurísticas para selecionar a quantidade de trabalho que será executada durante uma coleta - o conjunto da coleta. No entanto, o G1 deve coletar todos os objetos ativos em todas as regiões do conjunto da coleta sem parar. Portanto, se a heurística do coletor escolher um conjunto de coleta muito grande, o que pode acontecer se o comportamento do aplicativo for alterado e a heurística funcionar em dados "obsoletos", o coletor poderá exceder o destino da pausa.
Para atender ao objetivo de tempo de pausa fornecido pelo usuário, o JEP 344 faz com que o coletor de lixo G1 aborte o processo de coleta de lixo, dividindo o conjunto de regiões a serem coletadas em partes obrigatórias e opcionais. Pode abortar a coleta da parte opcional se a meta de tempo de pausa não for atingida de outra forma.
Outro problema do G1 é que nem sempre há tempo hábil para retornar a memória comprometida na heap do Java para o sistema operacional, uma vez que o G1 retorna apenas a memória heap do Java em um GC completo ou durante um ciclo concorrente. Como o JEP 346 apresenta:
Como o G1 tenta evitar completamente os GCs completos e só dispara um ciclo concorrente com base na atividade de ocupação e alocação de heap Java, ele não retornará a memória heap Java em muitos casos, a menos que seja forçado a fazê-lo externamente.
Esse comportamento é particularmente desvantajoso em ambientes de contêiner, no quais os recursos são pagos pelo uso.
O principal objetivo desta JEP é aprimorar o coletor de lixo G1 para retornar automaticamente a memória heap Java ao sistema operacional quando ocioso.
Assim como os aprimoramentos no G1, o JDK 12 adiciona um novo coletor de lixo experimental chamado Shenandoah, que tem como objetivo reduzir os tempos de pausa do GC fazendo o trabalho de evacuação concorrentemente com as threads Java em execução.
O Shenandoah foi desenvolvido pela Red Hat, sendo oferecido como uma opção de produção da distribuição JDK-8u do RHEL 7.5. É um coletor que marca / cópia e é similar em muitos aspectos ao G1. A principal diferença é que o coletor faz uso dos Brooks forwarding pointers durante a fase de evacuação. A ideia é que cada objeto no heap tenha um campo de referência adicional. Esse campo aponta para o próprio objeto ou, assim que o objeto é copiado para um novo local, aponta para seu novo local. Isso permitirá que ele libere objetos simultaneamente com threads que fazem alterações.
Os tempos de pausa com o Shenandoah são independentes do tamanho do heap, mas o coletor vem com uma penalidade de desempenho, portanto, é mais indicado para aplicativos com pilhas maiores. O algoritmo é descrito em profundidade neste artigo PPPJ2016.
Outros recursos do JDK 12 incluem:
- JEP 334: Propõe uma API para modelar descrições nominais dos principais artefatos de class-file e de tempo de execução, em particular constantes que são carregadas a partir de um pool de constante. O rascunho desta API está disponível aqui.
- JEP 230: Um conjunto de microbenchmarks, para testar facilmente o desempenho do JDK, baseado no Java Microbenchmark Harness (JMH).
- JEP 340: Há dois conjuntos de fontes diferentes do JDK para o ARM 64 bits. Um é contribuído pelo Oracle, arm64 e o outro é aarch64. Essa JEP removerá todas as origens relacionadas ao arm64, mantendo a versão ARM de 32 bits e o aarch64 de 64 bits.
- JEP 341: Compartilhamento de dados de classe (CDS) é um recurso para reduzir o tempo de inicialização e se beneficiar do compartilhamento de memória - a JEP menciona uma redução de 32% no tempo de inicialização executando o HelloWorld. No entanto, os usuários que desejam aproveitar o CDS, mesmo com apenas a lista de classes padrão, fornecida no JDK, devem executar java "-Xshare: dump" como uma etapa extra. Com esta JEP, o arquivo CDS será gerado por padrão.
O JDK 12 já está disponível para download
Mais sobre esse assunto
O arquiteto da linguagem Java Brian Goetz conversou com Wesley Reisz no podcast da InfoQ americana. Os dois começam com uma discussão sobre o que a cadência de seis meses significou para as equipes que desenvolvem a linguagem Java e, em seguida, examinam os recursos do Java 9 ao 12. Finalmente, os dois discutem os projetos paralelos de longo prazo (como Amber, Loom e Valhalla) e seu papel no processo de lançamento do JDK.