BT

Disseminando conhecimento e inovação em desenvolvimento de software corporativo.

Contribuir

Tópicos

Escolha a região

Início Artigos Recursos ausentes no Java: cinco anos depois

Recursos ausentes no Java: cinco anos depois

Pontos Principais

  • A linguagem Java mudou consideravelmente nos últimos cinco anos;

  • Dois grandes projetos que estão entregando tais mudanças - Valhalla e Amber - ainda estão em andamento;

  • O Java continua a manter seu principal valor de compatibilidade com as versões anteriores;

  • Apesar de ter 25 anos, a linguagem e plataforma ainda terão muito tempo de vida;

  • Novas tecnologias, como o Graal, estão ajudando a manter o Java na vanguarda das linguagens de programação.

Quase cinco anos atrás, escrevi um artigo descrevendo algumas idéias dos recursos presentes em outras linguagens que considerava benéficos para o Java. Muita coisa aconteceu desde então - naquela época, o Java 8 era o lançamento mais recente, enquanto a versão mais recente agora é o Java 14.

Vamos dar uma olhada em cada recurso e ver qual é seu atual status: se foi adicionado ao Java, se está a caminho ou se não está nos planos para inclusão.

Determinando os tipos parametrizados de um objeto

Minhas previsões originais descartaram as abstrações de tipos genéricos. Não previ a ambição que o projeto Valhalla tinha para refazer a JVM do zero.

Os principais objetivos do projeto Valhalla são:

  • aperfeiçoar o comportamento do layout da memória da JVM com o modelo de cálculo do hardware moderno;
  • estender os tipos genéricos, a fim de permitir abstração em todos os tipos, incluindo de tipos primitivos, valores e até void;
  • permitir que as bibliotecas existentes, especialmente o JDK, evoluam de maneira que a compatibilidade aproveite tais recursos em sua totalidade.

Omitida na descrição está a palavra "values", que evoluiu para o recurso que conhecemos hoje como inline classes.

A abstração de tipos genéricos e especialização de primitivos foram incluídos em um projeto muito maior que promete mudar fundamentalmente a maneira como o Java é escrito e executado.

Apesar das profundas mudanças que estão sendo feitas, os objetivos do projeto incluem minimizar a disruptura nos aplicativos Java existentes e fornecer uma solução fácil, abordagem opt-in para que os desenvolvedores usem os recursos do Valhalla em seu próprio código.

Devemos observar que o projeto Valhalla ainda está em andamento - e ainda não há um roadmap oficial para quando ele será entregue.

Veredicto: A CAMINHO (como parte do Projeto Valhalla)

Aritmética sem sinal

A possibilidade de suportar esse recurso vem sendo discutida repetidamente ao longo da história do Java, porém há inúmeras complexidades envolvendo sua introdução.

Por exemplo, há a questão de como a assinatura deve ser representada no sistema de tipos do Java e se deve estar visível a nível de bytecode da JVM ou não.

Esses problemas ainda não chegaram a um consenso satisfatório e, portanto, o Java ainda não inclui aritmética sem sinal - um aspecto notável do Projeto Valhalla é que ele não inclui suporte para aritmética sem sinal.

Veredicto: NÃO ESTÁ SENDO CONSIDERADO

Uso de long no índice de array

Os arrays no Java são limitados em tamanho pelo simples fato de seu design, pois assumem um int como índice. Isso significa que um array está limitado a 2**31 elementos (lembrando que são apenas os valores positivos) ou aproximadamente 2 bilhões de elementos.

Como originalmente previsto, a idéia de usar long em vez de int permitiria aos desenvolvedores criar e manipular arrays muito maiores. No entanto, o foco da comunidade nesta área mudou para fornecer acesso fácil a grandes arrays armazenados fora da pilha.

Existem várias razões para isso - a facilidade de interoperabilidade com bibliotecas não Java (incluindo aprendizado de máquina e outras aplicações pesadas) é uma delas. No entanto, também há perguntas sobre o quão útil seria ter grandes arrays na pilha. Arrays gigantes teriam custos de cópia significativos, ao entrar e sair da pilha do Java e poderiam causar sérias dores de cabeça ao coletor de lixo da JVM.

Por esses motivos, os grandes arrays são pensados principalmente no contexto de suporte fora da pilha, e o conceito foi incorporado aos recursos em desenvolvimento no Projeto Panamá.

Veredicto: A CAMINHO (como parte do Projeto Panama)

Sintaxe do import mais expressiva

Nenhuma tentativa séria foi feita para expandir o escopo da sintaxe do import ou para introduzir <pre>alias</pre>, mesmo no nível (ou no escopo do arquivo) local.

Veredicto: NÃO ESTÁ SENDO CONSIDERADO

Coleção de literais

No Java 9 foram adicionados métodos estáticos nas interfaces e as coleções foram atualizadas para incluir methods para criação de coleções. Eles desempenham o papel de coleção de literais no Java:

var ls = List.of(1,2,3);

Como esses métodos estão desempenhando o papel dos literais, essa mudança também introduziu novas implementações nas interfaces das coleções. Tais implementações são imutáveis, porque para reutilizar as coleções mutáveis ​​existentes (como ArrayList) violaria a expectativa do programador de que esses valores se comportassem como se fossem literais.

Soluções mais intrusivas, como a introdução direta de novos literais na sintaxe da linguagem, não tiveram continuidade.

Veredicto: ENTREGUE (por meio de métodos de construção)

Tipos de dados algébricos

Os tipos de dados algébricos em Java estão em processo de entrega. O recurso consiste em duas principais adições ao sistema de tipos: records e sealed types, bem como pattern matching, uma nova parte substancial da sintaxe.

O Java 14 fornece uma versão de visualização de dois desses aspectos - especificamente, records, que em Java são essencialmente denominados tuplas e os componentes iniciais de pattern matching.

Os novos recursos que compõem as partes introdutórias de pattern matching são em primeiro: o uso de pattern no instanceof e uma versão padronizada de expressões switch.

Em segundo, o scaffolding que, em última análise, permitirá a introdução da pattern matching gerais, de maneira semelhante às expressões de match com as quais os programadores Scala estão familiarizados.

Ainda há muitos passos a serem feitos antes que esse recurso seja totalmente entregue - os records e os patterns ainda estão apenas em pré-visualização. JEPs adicionais, incluindo o JEP 375, que estende a pattern para instanceof permite a desconstrução dos records, e são necessários para detalhar o pattern matching como um todo.

Desde a chegada do Java 14, os principais JEPs - incluindo o JEP 375 e o JEP 360, que introduz sealed types - não são direcionados a nenhuma versão específica do Java.

Apesar da falta de um roadmap concreto, é provável que a totalidade dos tipos de dados algébricos e o mecanismo de pattern matching possam ser entregues de forma padronizada a tempo do próximo lançamento LTS, que é o Java 17 em Setembro de 2021.

Veredicto: A CAMINHO (como parte do Projeto Amber)

Tipagem estrutural

O sistema de tipos do Java evoluiu um pouco desde o Java 8, mas na prática não houveram mudanças significativas em direção à tipagem estrutural. Por exemplo, quando os records estavam sendo projetados, a tipagem estrutural foi explicitamente rejeitada em favor de tornar os records como tipos nominais.

Isso reforça a idéia de que o nome que damos a um tipo tem poder e importância, pois os records no Java são definidos por mais do que apenas a quantidade e os tipos de seus componentes.

Um ponto menor onde algo se assemelha à tipagem estrutural continua sendo vagamente visível no Java, e está nos tipos não denotáveis. Isto é apenas uma extensão do exemplo discutido originalmente no artigo de 2015.

Naquele exemplo, construímos algo que se parece com um tipo estrutural (Objeto + <algum método>), mas só podemos usá-lo em uma única expressão, porque não há um tipo denotável que possamos usar como o tipo de uma variável que possamos atribuir um valor.

Desde o Java 10, a linguagem possui uma forma estendida de inferência de tipo que usa <pre>var</pre>, para reduzir o padrão das atribuições. Podemos usar esse recurso para estender o escopo no qual podemos chamar métodos adicionais definidos em um tipo. No entanto, isso é limitado ao método em que a inferência de tipo ocorre. O tipo especial que <pre>var</pre> infere não pode ser propagado através dos limites do método precisamente porque não é denotável.

Na realidade, esses casos especiais não são verdadeiramente tipos estruturais, e não há intenção de introduzi-los. A atração gravitacional da concepção do Java por nomes e digitação nominal é muito forte.

Veredicto: CONSIDERADO, MAS REJEITADO

Chamada de função dinâmica

Nos últimos cinco anos, houve uma grande expansão no uso do invokedynamic, embora apenas dentro do JDK e em um pequeno número de bibliotecas externas tecnicamente sofisticadas.

É fato que "a linguagem Java não possui uma palavra-reservada ou outra construção para criar chamadas de função dinâmicas para uso geral", como afirmou o artigo original.

A sugestão de que a biblioteca Dynalink pudesse ser expandida, a fim de assumir tal papel nunca aconteceu, e, de fato, a implementação do Javascript Nashorn que produziu o Dynalink agora é considerada descontinuada e pode ser omitida do Java 15 (embora o próprio Dynalink permaneça).

Essas bibliotecas que fazem uso de chamadas de funções dinâmicas as fazem por meio da API MethodHandles que, embora um pouco mais fácil de usar em 2020, ainda está fora do alcance da maioria dos programadores Java.

A dificuldade de encontrar um equilíbrio entre chamadas dinâmica que não causam muitos problemas em tempo de execução e o uso atraente no nível da linguagem se mostrou muito bom, pelo menos por enquanto.

Veredicto: NÃO ESTÁ SENDO CONSIDERADO

O que eu perdi?

Nos últimos 5 anos houve o surgimento de vários projetos e tendências que não previ ou mencionei no artigo original. Os maiores deles são talvez:

  • Extensão e escopo do Projeto Valhalla;
  • Projeto Amber;
  • Novo modelo de lançamento do Java;
  • Graal e GraalVM;
  • Surgimento do Kotlin.

Podemos destacar alguns exemplos:

Embora o Projeto Valhalla tenha sido iniciado em 2014, ele ganhou impulso e se expandiu enormemente ao longo dos anos. Tornou-se a maior e mais ambiciosa mudança que o Java já viu. O projeto Valhalla promete modificar todos os aspectos da plataforma Java - desde a forma como a memória e os valores são representados na VM, por meio do sistema de tipos e genéricos, até o nível das bibliotecas e sintaxe da linguagem.

Este projeto visa alinhar o Java com o estado atual e futuro dos hardwares e oferecer desempenho e outras melhorias que simplesmente não podem ser endereçadas separadamente. Como alternativa, o projetoValhalla visa mover o estado da plataforma Java de sua posição atual (que podemos pensar como máximas locais) para um lugar que é muito mais adequado para ser a base de uma plataforma para as próximas décadas.

Em uma pesquisa original é sempre difícil de prever e, portanto, talvez não seja surpreendente que a ascensão do Graal também tenha me pegado de surpresa. A ideia é básica, como muitos outros conceitos atraentes, muito simples, uma vez que você os tenha compreendido.

O compilador JIT do Java é escrito em C++ e executado em threads especiais dedicadas dentro da JVM. O Graal começa com uma ideia simples: e se, em vez disso, o compilador JIT fosse escrito em Java e as threads do compilador estavam na verdade executando uma segunda cópia do interpretador Java?

O compilador JIT em modo interpretado deve ser tão capaz quanto o JIT atual - portanto, ele poderia compilar qualquer arquivo .class em código de máquina. Devíamos esperar que fosse mais lento do que o compilador C ++ existente, mas não seria diferente em seu comportamento, apenas em desempenho.

Levando essa ideia à sua conclusão lógica, significa que o JIT de modo interpretado poderia compilar os arquivos .class que constituem o próprio JIT. Uma vez aquecido, ele poderia se substituir e funcionar com o mesmo desempenho do JIT nativo original.

Essa ideia intrigante acabou sendo o ponto de partida para uma grande classe de novas tecnologias, incluindo compilação nativa do Java (AOT), bem como uma nova máquina virtual poliglota (GraalVM) capaz de executar muitas linguagens diferentes.

Conclusões

A plataforma Java cresceu em sofisticação nos últimos cinco anos, com muitas novas linguagens e recursos da VM entregues ou em andamento. Supondo que as tendências continuem, é provável que a comunidade esteja mais interessada no conjunto de recursos que estarão disponíveis no Java 17 (previsto para Setembro de 2021).

Este será um Java muito diferente do que existia em 2014 quando fizemos nossas observações iniciais e, embora alguns recursos tenham sido entregues, parece claro que alguns outros provavelmente nunca serão e outros ainda foram realizados de uma forma muito diferente. Estamos ansiosos para ver o que os próximos cinco anos trarão para a linguagem e plataforma Java, em especial os aspectos que não podemos prever agora.

Sobre o autor

Ben Evans é cofundador da jClarity, uma empresa de otimização de desempenho da JVM. Ele é organizador do LJC (London's JUG) e membro do Comitê Executivo da JCP, ajudando a definir padrões para o ecossistema Java. Ben é um Java Champion; 3 vezes JavaOne Rockstar Speaker; autor do "The Well-Grounded Java Developer", da nova edição de "Java in a Nutshell" e "Optimizing Java". Ele palestrante regularmente sobre a plataforma Java, desempenho, arquitetura, concorrência, startups e tópicos relacionados. Ben às vezes está disponível para palestras, aulas, escrita e consultoria - entre em contato para obter os detalhes.

Avalie esse artigo

Relevância
Estilo/Redação

Conteúdo educacional

BT