Na Invillia, toda quarta-feira, ao meio dia, paramos uma hora para nos nutrir com as dicas, how-tos, boas práticas e tendências selecionadas por nossos especialistas em Product, Agile, Back e Front, Mobile, Quality, Security e Data. Uma troca de experiência vital para quem adora o novo. E essencial para que a inovação nunca pare. Se a tecnologia está no sangue, a gente faz questão de deixá-la circulando cada vez mais_
NA VEIA_ Modernização da linguagem e plataforma Java: paradigmas e mudanças na sintaxe que suportam essas atualizações.
12 minutos de leitura
No artigo de hoje, compartilhamos os principais aprendizados da incrível edição sobre o Java Moderno (JVM) apresentada por Rafael Souza, nosso especialista no assunto.
Ecossistema das linguagens e suas mudanças
Antes de falar dos paradigmas e mudanças na sintaxe que suportam as atualizações da linguagem e plataforma Java, é necessário entender “por quê” essas mudanças são tão impactantes, ou seja, as principais melhorias de cada uma, especialmente nas LTSs utilizadas pelo time da Invillia – da 7 a 11. Além disso, existe o conceito de frameworks e microframeworks cada vez mais evidentes que são Cloud Native em virtude de terem features desenhadas para rodar em cima da nuvem.
Assim, por mais que se fale bastante em inteligência de dados, os conceitos de Big Data, Machine Learning etc. são escritos em Python, e a plataforma que suporta os dados é praticamente toda implementada em Java.
Principais mudanças e novidades da versão do Java 7 e início do Java 8
- Lambda Expression – revigor que a linguagem deu no paradigma funcional, combinando a orientação a objetos com a parte de programação funcional, sendo que as expressões Lambda vieram para facilitar isso, deixando uma sintaxe mais próxima e flexível das notações que a visíveis se a linguagem fosse desenhada de forma funcional;
- Functional Interface– complementação das entregas e subentregas de implementação com palavras reservadas, tais como Default Method e Interface Static Method dentro de uma interface funcional, com método declarado (estático) e comportamento. A combinação de comportamentos para que se tenha só um método, ou seja, consiga fazer interface funcional, inserindo implementações intermediárias dentro do método declarado na interface. Há interfaces funcionais que possuem três parâmetros que, se forem do mesmo tipo, torna possível obter tanto a chave quanto o valor com o parâmetro para a interface funcional, ou seja, é bem robusto.
- Base64 – incluído no Java 8, quando até então não existia um método e uma linguagem para fazer em Code64, sendo necessário utilizar alguma biblioteca para essas facilitações. Pelo fato do Base64 ser padrão para fazer upstream de arquivos dentro de uma interface seguindo um nível de maturidade, ele “manda” como padrão até mesmo nos padrões de assinatura de cabeçalhos, pois esses protocolos de segurança geralmente codam chaves grandes sem inglês. Há a indicação de comitês para trazer a implementação de Base64 para a linguagem porque é bastante utilizada em serviços web, principalmente, com esses novos padrões de segurança.
Outras melhorias no Java 8
Foram modificados os caminhos para deixar ainda mais transparente o acesso ao sistema de arquivos, isso porque lidar com arquivo é um complicado dado que a JVM ganha de um lado e perde do outro. Assim, ter essa abstração em cima do sistema gerenciador de arquivos era muito complexo antes e suscetível a erro, por isso há boa parte das exceções em subclasses sem permissão de escrita.
Assim, foram criados esses facilitadores para dar uma segunda sintaxe favorecida na performance de acesso aos arquivos, compatível com containerenização e clusterização desde a época de seu lançamento, com acesso concorrente a arquivos e aumento das bibliotecas.
API de concorrência – a concorrência de acesso a arquivos no sistema e volumes não apenas dos contêiners foi abstraída visando facilitar para o desenvolvedor acessar esses recursos ligados e a partir de concorrência. Por isso, a programação assíncrona está ficando mais simples com recursos sendo adicionados nas linguagens.
Além disso, o próprio Java já utiliza um modelo mais moderno na versão atual de microprocessos que rodam num core específico e que serão modificados para um conceito de fibras parecido com o conceito de atores e play framework para quem programa em escala também, mostrando um pouco do diálogo do Java com essas outras linguagens da JVM.
Este modelo começou a ser evoluído com recursos Cloud Native, conteiners etc., sendo que a quantidade de processadores e memória onde se dispende recurso financeiro exige mais controle, por isso foi modificada a forma de acessar. E essas bibliotecas vieram para facilitar esse tipo de recurso. Paralelo a isso, o Java sempre tenta balançar o lançamento da sintaxe e da feature da linguagem suportando a plataforma como um todo.
Parallel Garbage Collector (GC) – foi tido como o mais performático até pouco tempo, com quantidade de threads para permitir que rode além da capacidade de desalocar memória pois os objetos vão consumindo memória e comprometendo o sistema de acesso ao disco e vários indicadores.
Permanente Generation – Mudou-se também a geração de memória tornando-a permanente, modificando a organização interna (mecanismos de geração da memória permanente) sem mudar a estrutura.
Muita coisa mudou no Java 8 e isso justifica ela ter sido a versão de suporte a longo prazo por tanto tempo, afinal, o Java 9 teve muita polêmica com o sistema de módulos inserido na raiz de cada pacote, além do incremento de fórmula que visa diminuir o nível de retrocompatibilidade das bibliotecas.
Considerando o planejamento de que o 10 fizesse a inferência disso, os módulos agora são inferidos e declarados de forma explícita, mas também podem ser implicados a partir da estrutura de pacotes convencional da sua solução.
Principais melhorias do Java 9
Já no Java 9, de forma explícita, ganhou-se duas ferramentas muito poderosas: JLink (para criar metamodelo a partir do JDeps) e JDeps (para realizar a navegação visando captar as dependências com seus requisitos e bibliotecas externas, ou seja, para criar um mapa desse gráfico de dependências, sendo que o JLink cria uma JRE específica para o projeto).
Em virtude do início deste movimento de depreciação das bibliotecas antigas e implementações específicas, elas começaram a ser depreciadas para serem removidas da plataforma Java, JVM e JDK e virarem bibliotecas externas. Daí a ideia de estender aos desenvolvedores, orquestrando ali o motor de construção para ter uma JRE que não tenha as classes e nem precise diminuir Foot prints de memória, tempo de classloader etc.
Trata-se, portanto, de ferramentas de tuning que estão disponíveis e sendo utilizadas implicitamente pelos motores de construção a fim de ficarem cada vez mais próximos. A denominação de “multi” para a plataforma e linguagem também possibilitou a utilização de várias linguagens com a compilação nativa através dos seguintes mecanismos:
- JShell – ferramenta de linha de comando no console que ganha a possibilidade de ser interpretada sem compilar se aproximando da linguagem interpretada sendo muito bem-vinda;
- Implementação de HTTP/2 – eventos enviados pelo servidor e a compressão dos Headers cujos padrões de cabeçalhos ficaram cada vez maiores suportando compressão a nível de camada de rede, camada de aplicação HTTP, oportunidades embutidas dentro do Java 9.
Lançamento do Java 10
Muito ofuscado pelo tumulto que o Java 9 causou com o sistema de módulos, o Java 10 possui inferência local de tipo, sendo mais uma palavra reservada na lista de palavras reservadas – War –, que significa inferência de tipo, ou seja, quando um método retorna um tipo bem conhecido não é necessário declarar na variável +, ótimo em termos de legibilidade, afinal hoje, é sempre ideal conceber nomes bons para as variáveis, coisa que antigamente deixava as pessoas inibidas de sugerir um nome de variável muito grande acima de 30 caracteres por conta da tipagem.
No Java 10 isso também funciona nos “loops” apesar da sintaxe “string”, tanto para pegar elementos usando o enumerador quanto para fazer um laço imperativo. Por isso, são inseridas funcionalidades compatíveis com vários paradigmas, como o paradigma funcional é compatível com os paradigmas interativos, tradicionais, dentre outros.
O Parallel Garbage Collector GC for G1 implementação, por exemplo, ocorre full paralelo, utilizando as funcionalidades implementadas anteriormente de programação assíncrona (para ser mais performático). Além disso, entre as características que suportam a plataforma para o tuning da JVM pode-se mencionar que durante bom tempo a JVM foi considerada lenta durante a aplicação.
No Java 10 foram criados novos parâmetros de class data compartilhado para diminuir o “down time” quando for necessário realizar as escalas horizontais, para subir e importar diminuindo esse tempo de aquecimento como um todo.
Uma das principais curiosidades do Java 10 é que, desde as versões portadas para rodarem dentro do docker – outro tipo de abstração para o sistema operacional com controle de acesso aos recursos diferentes do que a máquina virtual esperava ou estava acostumada – ele se popularizou, e as pessoas migraram para o Java.
No entanto, pouca gente percebeu que o comando mostra a quantidade de memória para o Java e, através dele, antes das versões 8 ou 9.1, se considera o percentual de memória como da máquina host e não do contêiner. Assim, por mais que se escolha contêiner com 2GB de memória RAM, se a máquina tiver 32GB de RAM, o Java vai explorar os contêiners com grande frequência.
Isso foi corrigido na implementação do Java 10 e portado para trás desde a versão 9.1 do Java 8 passando até a enxergar a memória gerenciada pelo contêiner e não pela máquina, o que também vale para a quantidade de processadores. Hoje qualquer imagem já se comporta da forma esperada.
Funcionalidades do Java 11
Penúltimo LTS agora com o lançamento do 17 que tem como primeira funcionalidade a importância de se comportar como se fosse uma linguagem interpretada em virtude de DevOps e provisionamento de infraestrutura, há muito script em organizações antigas escritos em linguagens pouco acessíveis. Assim, como o mercado borbulha e demanda muito Java, principalmente Enterprise, foram migradas as aplicações para Enterprise fazendo sentido também migrar outros ferramentais.
Um operador do Linux permite executar um trecho ou arquivo específico para escrever a linguagem Java completa, dado que desde o Java 10 há acesso a tipos internos, pode-se declarar todos os tipos no mesmo arquivo sem a necessidade de gravar um tipo para cada arquivo com uma ideia, fazendo acesso alinhado a classes dentro do mesmo arquivo. Ou seja, é possível executar um arquivo passando o Java como parâmetro, de forma interpretada e compilada sob demanda desde o Java 11.
Depois de tantas evoluções de plataforma (Java 9 introduziu uns módulos e Java 10 corrigiu muitas coisas de acesso à memória), no Java 11 há mais mudanças no que diz respeito à sintaxe da linguagem: inferência de tipo nas expressões Lambda com algumas restrições como o acréscimo de inferência de tipo, em todos os parâmetros ou em nenhum e essa sintaxe precisa estar em parênteses. Por fim, a nova versão é bem intuitiva e online.
História do Java
A história do Java teve início com a versão 1.0 em 1996 com a nomenclatura confusa de “JDK 1.0”, 1.1, 1, que, mais tarde, ganhou o título de J2SE 1.3, quando começou a ser compilada para outras arquiteturas, desvencilhando o Java mobile da versão Standart utilizada para aplicações – esta foi a primeira diferenciação.
Já na migração da versão 5 para a versão 6, o nome foi trocado para Java SE para diferenciar da versão anterior.
Mais tarde, em 2006, foi lançado o Java SE5 Enterprise com bibliotecas destinadas a distribuições corporativas, por exemplo, JMS a partir de filas, ou seja, bibliotecas específicas que ficam nos provedores dos contêineres de aplicação compatíveis com uma Enterprise Edition, caminhando até a versão 8 que foi a LDS durante muito tempo – e vai ser até 2030 ao que tudo indica.
Em nível de comparação e benchmarking, a primeira versão do Java é antiga, datada de 1996, e a primeira versão de Python é de 1991, sendo que as versões Javascript e Ruby foram lançadas em 1995. Por isso, é correto dizer que as linguagens de desenvolvimento web foram evoluindo ao longo do tempo sendo a PHP uma das mais utilizadas.
O The Java Version Almanac é uma página interessante que mostra todas as versões da linguagem Java, quando foram lançadas e compara quais JSRs fazem parte de cada versão usando a pirâmide invertida – do Java 16 ao Java 4 – mostrando todas JSRs implementadas e aceitas nesse intervalo de tempo.
A proposta do Java sempre foi lançar versões novas a cada seis meses, sendo que a cada três anos surge uma versão LTS. O Oracle quer diminuir esse intervalo para dois anos, o que provocaria encurtamento desse suporte tanto para trás (diminuindo o espaço de seis para quatro anos da versão anterior) quanto para a frente (nas próximas atualizações).
Essa discussão é interessante financeiramente e voltou à tona recentemente para todos os círculos de engenharia de software com o Linux Toward, que possui tópico para atualizar a linguagem, encurtando os ciclos de vida.
Se esta definição sair neste ano, a próxima versão de longo suporte deixará de ser a 23 e passará a ser a 21. Essa explicação dentro da linha do tempo mostra que a 8 ainda não possui definição sobre o prazo de fim de vida, a 11 vai terminar assim que for lançada a próxima deixando de ser LTS, e a 8, ao que tudo indica, seguirá com suporte até 2030.
Modernização da linguagem e plataforma Java
A linguagem Java é construída de forma colaborativa e fundamentada em três pilares para a tomada de decisão:
- Multiparadigma – que suporta a programação orientada a objetos, sendo funcional, procedural, imperativa, relativa etc., e com igual espaço, ou seja, equilibrada;
- Portabilidade – que permite execução em diversas infraestruturas e sistemas;
- Retrocompatibilidade – que executa por meio do código sem grandes mudanças.
Há ainda muita discussão sobre a linguagem Enterprise ser “lenta” por conta da memória e cujo crescimento se deu de maneira não muito estruturada durante alguns anos, além da transição da ação da Oracle para a comunidade ter sido um pouco conturbada. Entretanto, no momento, a linguagem já está mais estável, performática e centrada na comunidade, ou seja, feita pela e para a comunidade.
Assim, há toda uma topologia de processos e grupos criados para suportar as funcionalidades que entram ou não na linguagem, dentre os quais:
- JSR – requisição de especificação feita por grupo de especialistas que escreve a técnica formal para esclarecer como será implementado o processo;
- JCB – caminho de processo por meio de votação sobre JSRs que vão entrar para cada versão do Java;
- JUG – principais componentes desses JCPs e grupos de usuários Java.
A portabilidade desses processos garante que o usuário não fique preso a um único provedor de linguagem através de diversas distribuições diferentes (fundamentadas nessas especificações) abertas para todo mundo. Isso porque o processo e prazos dentro de um grupo de especialistas permite adoção de uma espécie ou especificação na linguagem de maneira acessível.
Comunidade colaborativa SouJava
SouJava é a maior comunidade do Brasil com sede em São Paulo, Campinas e Rio de Janeiro com especificações desenvolvidas majoritariamente por desenvolvedores brasileiros, a exemplo do JavaMoney (implementação de valores financeiros) e JavaMetrics (cálculo da distância, altura e diferentes medidas etc.). Essas bibliotecas ainda não entraram na especificação, mas estão na dependência do Java mãe/líder para realizar conversões de maneira mais seguras.
Além disso, o Java continua sendo grátis e sua proposta de linguagem é simples porque é desenvolvida pela comunidade SouJava. Entretanto, atualmente, ela tem novo processo de lançamento de versões LTS de suporte a longo prazo, necessário para garantir a retrocompatibilidade (feature da linguagem Java) num escopo menor e fechado, ou seja, garantindo que não seja necessário “rebase” de versões já lançadas anteriormente.
Na Invillia temos o know-how e a experiência nas tecnologias, abordagens e metodologias mais inovadoras do mercado, sugerindo e aplicando em cada caso. Estamos sempre estudando, enriquecendo conhecimentos, antecipando o que está por vir, testando, indo mais além. Criamos e continuamente aprimoramos ao lado de quem está revolucionando seus mercados com produtos e serviços digitais inovadores, resilientes, robustos, escaláveis e com a melhor experiência de utilização. E tudo isso a partir de um ponto: nosso Global Growth Framework _
Vamos construir o futuro juntos?