JavaRush /Blogue Java /Random-PT /De 8 a 13: uma visão completa das versões Java. Parte 2

De 8 a 13: uma visão completa das versões Java. Parte 2

Publicado no grupo Random-PT
Este artigo é a segunda parte da minha revisão das inovações nas versões 8 a 13 do Java. A primeira parte está aqui . Sem mais delongas, vamos em frente: até 25 de setembro de 2018, quando o novo JDK foi lançado:

Java 11

De 8 a 13: uma visão completa das versões Java.  Parte 2 - 1

var (em lambda)

De agora em diante, podemos especificar os tipos de parâmetros lambda ou omiti-los ao escrever uma expressão lambda (expressões lambda digitadas implicitamente):
Function<String, String> append = (var string) -> string + " Text";
String appendedString = append.apply("Some");
System.out.println(appendedString);
Você também pode adicionar anotações aos parâmetros lambda sem precisar escrever o nome completo do tipo de variável:
Function<String, String> append = (@NonNull var string) -> string + " Text";

Z(ZGC)

ZGC é um novo coletor de lixo que não funciona. Ele aloca nova memória, mas nunca a reinicia. O ZGC promete gerenciar grandes quantidades de memória com alto rendimento e baixa latência (o ZGC está disponível apenas em plataformas de 64 bits). Coloração de referência - ZGC usa ponteiros de 64 bits com uma técnica chamada coloração de ponteiro. Ponteiros coloridos armazenam informações adicionais sobre objetos no heap. Quando a memória fica fragmentada, isso ajuda a evitar a degradação do desempenho quando o GC precisa encontrar espaço para uma nova alocação. A coleta de lixo usando ZGC consiste nas seguintes etapas:
  1. paradas mundiais: procuramos pontos de partida para alcançar objetos no heap (como variáveis ​​locais ou campos estáticos);
  2. interseção de gráficos de objetos a partir de links raiz. Marcamos cada objeto que alcançamos (ZGC percorre o gráfico de objetos e examina os marcadores coloridos, marcando os objetos disponíveis);
  3. lidar com alguns casos extremos, como links fracos;
  4. mover objetos vivos, liberando grandes áreas da pilha para acelerar a alocação.
  5. quando a fase de movimentação começa, o ZGC divide o heap em páginas e trabalha uma página por vez;
  6. O ZGC finaliza o movimento de quaisquer raízes e o restante do movimento ocorre.
Este tópico é muito complexo e confuso. Uma discussão detalhada exigiria um artigo separado, então deixarei aqui:

Épsilon GC

Epsilon é um coletor de lixo que lida com a alocação de memória, mas não implementa nenhum mecanismo real de recuperação de memória. Assim que o heap Java disponível se esgotar, a JVM será encerrada. Ou seja, se você começar a criar um objeto em um array infinito sem vincular a uma referência com esse coletor de lixo, a aplicação irá travar com um OutOfMemoryError (e se for com qualquer outro, não irá, pois irá limpar objetos sem referências) . Por que é necessário? Aqui está o porquê:
  1. Teste de performance.
  2. Teste de pressão de memória.
  3. Testando a interface da VM.
  4. Trabalho extremamente curto.
  5. Melhorias na latência da última gota.
  6. Melhorias no rendimento de última gota.
Links Úteis: Outras inovações:
  1. ByteArrayOutputStreamtenho um método void writeBytes(byte [])que grava todos os bytes do argumento em OutputStream.
  2. FileReadere FileWriterobtive novos construtores que permitem especificar Charset.
  3. Pathpegou dois novos métodos, of(String, String [])retorna Pathde um argumento de string um caminho ou sequência de strings que quando combinadas formam uma string de caminho e of(URI): retorna Path de um URI.
  4. Pattern— recebeu um método asMatchPredicate()que verifica se uma determinada string de entrada corresponde a um determinado padrão (se permite criar um predicado usando uma expressão regular para que você possa, por exemplo, filtrar dados em stream).
  5. StringEu peguei muitos métodos úteis, como:
    • String strip(): nos retornará uma string que é esta string, com todos os espaços no início e no final da string removidos (semelhante a trim(), mas define os espaços de forma diferente);
    • String stripLeading(): nos retornará a string que é esta string, removendo quaisquer espaços iniciais da string;
    • String stripTrailing(): nos retornará a string que é esta string, removendo quaisquer espaços no final da string;
    • Stream lines(): nos retornará Streamfrom String, extraído desta string, separados por separadores de linha;
    • String repeat(int): nos retornará uma string que é uma concatenação dessa string, repetida várias vezes.
    • boolean isBlank(): retornará verdadeiro se a string estiver vazia ou contiver apenas espaços; caso contrário, falso.
  6. Thread— os métodos destroy() e stop(Throwable) foram removidos.
  7. Filestem uma série de novos métodos:
    • String readString(Path): lê todos os dados de um arquivo em uma string, enquanto decodifica de bytes para caracteres usando a codificação UTF-8;
    • String readString(Path, Charset): igual ao método acima, com a diferença de que a decodificação de bytes para caracteres ocorre usando o Charset especificado;
    • Path writeString (Path, CharSequence, OpenOption []): grava uma sequência de caracteres em um arquivo. Os caracteres são codificados em bytes usando a codificação UTF-8;
    • Path writeString(Path, CharSequence,Charset, OpenOption []): O mesmo método acima, apenas os caracteres são codificados em bytes usando a codificação especificada em Charset.
Estas foram as inovações de API mais interessantes (na minha humilde opinião), aqui estão alguns materiais para uma revisão mais detalhada:

Java 12

Seis meses se passam e vemos o próximo estágio na evolução do Java. Então, é hora de pegar uma pá de conhecimento e cavar. De 8 a 13: uma visão completa das versões Java.  Parte 2 - 2

Atualizar G1

As seguintes melhorias foram feitas para G1:
  1. Recuperar memória alocada não utilizada

    Na memória heap Java existe memória não utilizada (ou em outras palavras, inativa). No Java 12 eles decidiram corrigir esse problema, agora:

    • G1 retorna memória do heap em um GC completo ou durante um loop paralelo; G1 tenta impedir um GC completo e inicia um loop paralelo com base na alocação de heap. Teremos que forçar o G1 a retornar a memória do heap.

    Essa melhoria se concentra no desempenho, retornando automaticamente a memória do heap para o sistema operacional quando o G1 não está em uso.

  2. Abortando coleções mistas quando o tempo de pausa é excedido

    O G1 utiliza um mecanismo de análise para selecionar a quantidade de trabalho necessária para a coleta de lixo. Ele coleta objetos vivos sem parar após definir o conjunto e iniciar a limpeza. Isso faz com que o coletor de lixo exceda sua meta de tempo de pausa. Na verdade, esse problema é resolvido pela melhoria, pois se o tempo de execução da próxima etapa ultrapassar os limites razoáveis, esta etapa poderá ser interrompida.

Microbenchmark

Java 12 introduziu testes de microbenchmarking para que o desempenho da JVM possa ser facilmente testado usando benchmarks existentes. Isso seria muito útil para quem deseja trabalhar na própria JVM. Os testes adicionados são criados usando Java Microbenchmark Harness (JMH). Esses testes permitem testes contínuos de desempenho na JVM. O JEP 230 propõe a introdução de aproximadamente 100 testes, com novos testes introduzidos à medida que novas versões do Java são lançadas. Aqui está um exemplo dos testes sendo adicionados .

Shenandoah

Este é um algoritmo de coleta de lixo (GC) cujo objetivo é garantir tempos de resposta baixos (o limite inferior é de 10 a 500 ms). Isso reduz o tempo de pausa do GC ao realizar o trabalho de limpeza simultaneamente com a execução de threads Java. No Shenandoah, o tempo de pausa é independente do tamanho do heap. Isso significa que o tempo de pausa será o mesmo, independentemente do tamanho do seu heap. Este é um recurso experimental e não está incluído na versão padrão (Oracle) do OpenJDK.

Melhorar a mudança

Java 12 melhorou as expressões Switch para correspondência de padrões. Uma nova sintaxe L → foi introduzida. Aqui está uma lista dos pontos-chave da nova opção :
  1. A nova sintaxe elimina a necessidade de uma instrução break para evitar erros.
  2. As expressões de troca não falham mais.
  3. Além disso, podemos definir múltiplas constantes em um único rótulo.
  4. o caso padrão agora é necessário em expressões switch.
  5. break é usado em expressões Switch para retornar valores do próprio registro (na verdade, um switch pode retornar valores).
Vejamos isso como um exemplo:
var result = switch (someDay) {
  case "M", "W", "F" -> "MWF";
  case "T", "TH", "S" -> "TTS";
  default -> {
      if(someDay.isEmpty())
            break "Please insert a valid day.";
      else
            break "Looks like a Sunday.";
  }
};
Guia definitivo para alternar expressões em Java 13 Outros novos recursos:
  1. String:

    transform(Function f)- Aplica a função fornecida a uma string. O resultado pode não ser uma string.
    indent(int x)— adiciona x espaços à string. Se o parâmetro for negativo, esse número de espaços iniciais será removido (se possível).

  2. Files- pegou um método como mismatch(), que, por sua vez, encontra e retorna a posição do primeiro byte incompatível no conteúdo de dois arquivos, ou -1L se não houver incompatibilidade.

  3. Uma nova classe apareceu -CompactNumberFormat para formatar um número decimal em formato compacto. Um exemplo desta forma compacta é 1M em vez de 1.000.000. Assim, apenas dois dois são necessários em vez de nove caracteres.

  4. Há também um novo enum , NumberFormatStyleque possui dois valores - LONG e SHORT.

  5. InputStream obtive o método skipNBytes(long n) : pule o enésimo número de bytes do fluxo de entrada.

Links interessantes do Java 12:

Java 13

O mundo não fica parado, ele se move, ele se desenvolve, assim como o Java – Java 13. De 8 a 13: uma visão completa das versões Java.  Parte 2 - 3

Bloco de texto

Java sempre sofreu um pouco quando se trata de definir strings. Se precisávamos definir uma linha com um espaço, uma quebra de linha, uma aspa ou qualquer outra coisa, isso causava algumas dificuldades, então tivemos que usar caracteres especiais: por exemplo, \n para uma quebra de linha, ou escapar de alguma linha em si. Isso reduz significativamente a legibilidade do código e leva mais tempo ao escrever essa linha. Isso se torna especialmente perceptível ao escrever strings que exibem JSON, XML, HTML, etc. Como resultado, se quisermos escrever um Json pequeno, ele será parecido com isto:
String JSON_STRING = "{\r\n" + "\"name\" : \"someName\",\r\n" + "\"site\" : \"https://www.someSite.com/\"\r\n" + "}";
E então o Java 13 entra em cena e nos oferece sua solução na forma de aspas duplas triplas antes e depois do texto (que eles chamam de blocos de texto). Vejamos o exemplo json anterior usando esta inovação:
String TEXT_BLOCK_JSON = """
{
    "name" : "someName",
    "site" : "https://www.someSite.com/"
}
""";
Muito mais simples e claro, não é? Também foram adicionados Stringtrês novos métodos , respectivamente, para gerenciamento desses blocos:
  • stripIndent(): Remove espaços aleatórios de uma string. Isso é útil se você estiver lendo strings multilinhas e quiser aplicar o mesmo tipo de exclusão aleatória de espaços em branco que ocorre com uma declaração explícita (essencialmente simulando o compilador para remover espaços em branco aleatórios);
  • formatted(Object... args ): semelhante a format(String format, Object... arg), mas para blocos de texto;
  • translateEscapes(): Retorna uma string com sequências de escape (como \r) traduzidas para o valor Unicode correspondente.

Melhorar a mudança

As expressões switch foram introduzidas no Java 12 e 13 as refinam. Em 12 você define valores de retorno usando break. Em 13, o valor de retorno foi substituído pelo rendimento. Agora, a expressão switch que tínhamos na seção Java 12 pode ser reescrita como:
var result = switch (someDay) {
  case "M", "W", "F" -> "MWF";
  case "T", "TH", "S" -> "TTS";
  default -> {
      if(someDay.isEmpty())
          yield "Please insert a valid day.";
      else
          yield "Looks like a Sunday.";
  }
};
Embora fosse normal para nós, programadores já familiarizados com Java, aceitarmos o break, ainda assim era bastante estranho. O que a verdade está tentando me dizer? A nova (relativamente nova) palavra-chave yield é mais clara e pode aparecer em outros locais no futuro onde os valores serão retornados. Para aqueles que estão profundamente interessados ​​neste tópico, recomendo que você se familiarize com estes materiais:

Arquivos CDS Dinâmicos

CDS - Compartilhamento de Dados de Classe. Permite empacotar um conjunto de classes comumente usadas em um arquivo que pode ser carregado posteriormente por diversas instâncias de JVM. Por que nós precisamos disso? O fato é que no processo de carregamento de classes, a JVM realiza muitas ações que consomem muitos recursos, como ler classes, armazená-las em estruturas internas, verificar a exatidão das classes lidas, procurar e carregar classes dependentes, etc. ., e só depois de tudo isso as aulas estão prontas para funcionar. Compreensivelmente, muitos recursos são desperdiçados, já que as instâncias JVM muitas vezes podem carregar as mesmas classes. Por exemplo String, LinckedList, Inteiro. Bem, ou classes do mesmo aplicativo, e tudo isso são recursos. Se realizássemos todas as etapas necessárias apenas uma vez e depois colocássemos as classes redesenhadas em um arquivo que pudesse ser carregado na memória de várias JVMs, isso poderia economizar significativamente espaço de memória e reduzir o tempo de inicialização do aplicativo. Na verdade, o CDS torna possível criar exatamente esse arquivo. Java 9 permitiu apenas que classes de sistema fossem adicionadas ao arquivo. Java 10 - inclui classes de aplicativos no arquivo. A criação de tal arquivo consiste em:
  • criando uma lista de classes carregadas pela aplicação;
  • criando um arquivo muito necessário com as classes que encontramos.
A inovação no Java 13 melhora o CDS para que ele possa criar um arquivo quando o aplicativo terminar. Isso significa que as duas etapas acima serão agora combinadas em uma. E mais um ponto importante: apenas as classes que foram carregadas enquanto o aplicativo estava em execução serão adicionadas ao arquivo. Em outras palavras, aquelas classes que ainda estão contidas em application.jar, mas por algum motivo não foram carregadas, não serão adicionadas ao arquivo.

Atualizar API de soquete

A API Socket ( java.net.Socket e java.net.ServerSocket ) é essencialmente parte integrante do Java desde o seu início, mas os soquetes nunca foram atualizados nos últimos vinte anos. Escritos em C e Java, eles eram muito, muito volumosos e difíceis de manter. Mas o Java 13 decidiu fazer seus próprios ajustes em todo esse assunto e substituiu a implementação base. Agora, em vez de PlainSocketImpl, a interface do provedor foi substituída por NioSocketImpl . Esta nova implementação codificada é baseada na mesma infraestrutura de back-end do java.nio . Essencialmente, a classe usa o cache de buffer java.util.concurrent e o mecanismo de bloqueio (que são baseados em segmentos) em vez de métodos sincronizados. Não requer mais código nativo, facilitando a portabilidade para diferentes plataformas. Ainda assim, temos uma maneira de voltar a usar o PlainSocketImpl , mas a partir de agora o NioSocketImpl é usado por padrão .

Retorno de memória para ZGC

Como lembramos, o coletor de lixo Z foi introduzido no Java 11 como um mecanismo de coleta de lixo de baixa latência para que a pausa do GC nunca exceda 10 ms. Mas, ao mesmo tempo, ao contrário de outros HotSpots virtuais de GC, como Shenandoah e G1, ele poderia retornar memória dinâmica não utilizada para o sistema operacional. Esta modificação adiciona esta capacidade J ao ZGC. Conseqüentemente, obtemos menor consumo de memória junto com desempenho aprimorado, e o ZGC agora retorna a memória não comprometida ao sistema operacional por padrão até que o tamanho mínimo de heap especificado seja atingido. Mais uma coisa: o ZGC agora tem um tamanho de heap máximo suportado de 16 TB. Anteriormente, 4 TB era o limite. Outras inovações:
  1. javax.security- adicionou uma propriedade jdk.sasl.disabledMechanismspara desabilitar mecanismos SASL.
  2. java.nio- um método foi adicionado FileSystems.newFileSystem (Path, Map <String,?>)- respectivamente, para criar um novo arquivo.
  3. As classes java.nioagora têm métodos absolutos (em oposição a relativos) gete setmétodos. Eles, como a classe abstrata base Buffer, incluem um método slice()para recuperar parte do buffer.
  4. Adicionados javax.xml.parsersmétodos para instanciar fábricas DOM e SAX (com suporte a namespace).
  5. O suporte Unicode foi atualizado para a versão 12.1.
Links interessantes sobre Java 13:

Resultados

Poderíamos revisar as inovações anunciadas no Java 14, mas como ele verá a luz em breve - o lançamento do JDK 14 está programado para 17 de março de 2020, seria melhor realizar uma revisão completa e separada dele imediatamente após seu lançamento . Gostaria também de chamar sua atenção para o fato de que em outras linguagens de programação com longos intervalos entre lançamentos, como Python 2–3, não há compatibilidade: ou seja, se o código for escrito em Python 2, você preciso trabalhar duro para traduzi-lo para 3. Java é especial nesse aspecto porque é extremamente compatível com versões anteriores. Isso significa que seu programa Java 5 ou 8 será executado em uma máquina virtual Java 8-13 — com algumas exceções com as quais você não precisa se preocupar por enquanto. É claro que isso não funciona ao contrário: por exemplo, se seu aplicativo usa funções Java 13 que simplesmente não estão disponíveis na JVM Java 8. É tudo o que tenho por hoje, respeito a quem leu até aqui)) De 8 a 13: uma visão completa das versões Java.  Parte 2 - 5
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION