Mostrando postagens com marcador Desenvolvimento. Mostrar todas as postagens
Mostrando postagens com marcador Desenvolvimento. Mostrar todas as postagens

terça-feira, 27 de janeiro de 2026

🗂️ Acessando Arquivos Usando Java com Samba JCIFS

1. Introdução

Capacidades de intercâmbio de arquivos entre plataformas são cruciais para a operação de redes de computadores. Podemos fornecê-las com o protocolo Server Message Block (SMB) e sua implementação de código aberto amplamente difundida, o Samba.

Neste tutorial, aprenderemos como acessar recursos Samba a partir do Java, sem a necessidade de montar ou mapear uma unidade de rede.


2. A biblioteca JCIFS

O Common Internet File System (CIFS) é um dialeto do SMB. Usaremos a implementação codelibs JCIFS, que suporta o mais recente protocolo SMB3.

Vamos adicioná-la com a dependência do Maven:

<dependency>
    <groupId>org.codelibs</groupId>
    <artifactId>jcifs</artifactId>
    <version>3.0.1</version>
</dependency>

3. Configurando um Servidor Samba

💻 Ao longo deste tutorial, usaremos o servidor Samba configurado em uma máquina convidada do VirtualBox. Como convidado, escolhemos o servidor Ubuntu.

Em seguida, vamos configurar o adaptador de rede somente hospedeiro do VirtualBox. Então, estreitamos o intervalo de endereços DHCP para um único endereço IP: 192.168.56.101. Este truque nos poupa uma configuração de IP estático mais sofisticada.

Durante a instalação do sistema convidado, vamos adicionar o usuário `jane`. Depois, precisamos instalar o Samba e adicionar `jane` aos usuários do Samba:

$ sudo smbpasswd -a jane

Precisamos de duas pastas para os compartilhamentos:

$ mkdir /srv/samba/public /srv/samba/sambashare

Para expor as pastas, definimos a permissão 777 nelas:

$ sudo chmod 777 /srv/samba/public /srv/samba/sambashare

Agora, vamos editar o arquivo `/etc/samba/smb.conf`:

$ sudo nano /etc/samba/smb.conf

Então adicionamos duas seções para compartilhamentos:

[publicshare]
   comment = Anonymous Samba share
   path = /srv/samba/public
   read only = no
   guest ok = yes
   guest only = yes

[sambashare]
   comment = Samba on Ubuntu
   path = /srv/samba/sambashare
   read only = no
   browsable = yes

Desta forma, criamos dois compartilhamentos Samba: um `publicshare` anônimo e um `sambashare` protegido por senha.


4. Exemplo Simples

🔍 Vamos executar um código simples para ver o básico de alcançar um compartilhamento Samba. Verificaremos um arquivo localizado no `publicshare`:

// Contexto padrão
CIFSContext context = SingletonContext.getInstance();

LOGGER.info("#  Verificando se o arquivo existe");
try (SmbFile file = new SmbFile("smb://192.168.56.101/publicshare/test.txt", context)) {
    if (file.exists()) {
        LOGGER.info("Arquivo " + file.getName() + " encontrado!");
    } else {
        LOGGER.info("Arquivo " + file.getName() + " não encontrado!");
    }
}

Podemos notar os elementos necessários para estabelecer a comunicação:

  • CIFSContext mantém a configuração do cliente, credenciais e outras informações relacionadas. Aqui, é uma instância de `SingletonContext`, que fornece credenciais adequadas para uma conta anônima.
  • SmbFile, que representa qualquer tipo de recurso Samba. No nosso caso, este é um arquivo. Podemos colocá-lo em um bloco try-with-resource.

Finalmente, usamos o método `exists()` no objeto de arquivo.


5. Autenticação

🔐 Podemos criar o objeto `CIFSContext` com credenciais. Vamos listar os elementos no compartilhamento protegido por senha `sambashare`:

NtlmPasswordAuthenticator credentials = new NtlmPasswordAuthenticator(
    "WORKGROUP",    // Nome do domínio
    "jane",         // Nome de usuário
    "Test@Password" // Senha
);

// Contexto com autenticação
CIFSContext authContext = context.withCredentials(credentials);

LOGGER.info("# Fazendo login com usuário e senha");
try (SmbFile res = new SmbFile("smb://192.168.56.101/sambashare/", authContext)) {
    for (String element : res.list()) {
        LOGGER.info("Elemento encontrado " + element);
    }
}

Primeiro, criamos o objeto `NtlmPasswordAuthenticator` para armazenar as credenciais. Em seguida, chamamos o método `withCredentials()` no objeto de contexto existente. Como resultado, obtivemos um `authContext` filho com nossas credenciais. Finalmente, a função `list()` mostrou todos os componentes do compartilhamento.


6. Trabalhando com Arquivos e Diretórios

📂 O JCIFS fornece um conjunto abrangente de funções para operar em arquivos e pastas. Vamos dar uma olhada em algumas delas.

6.1. Listando e Verificando Arquivos

Com `listFiles()`, podemos listar arquivos e pastas. Ele retorna um objeto `SmbFile`, que permite o uso de muitas funções de verificação:

LOGGER.info("# Listar arquivos e pastas no compartilhamento Samba");
try (SmbFile res = new SmbFile("smb://192.168.56.101/publicshare/", context)) {
    for (SmbFile element : res.listFiles()) {
        LOGGER.info("Elemento Samba encontrado de nome: " + element.getName());
        LOGGER.info("    O elemento é arquivo ou pasta: " + (element.isDirectory() ? "pasta" : "arquivo"));
        LOGGER.info("    Tamanho: " + element.length());
        LOGGER.info("    Última modificação: " + new Date(element.lastModified()));
    }
}

Neste exemplo, iteramos por todos os itens na pasta pública. Determinamos se é um arquivo ou um diretório usando o método `isDirectory()`. Em seguida, recuperamos seu tamanho e tempo de modificação com os métodos `length()` e `getLastModified()`, respectivamente.

6.2. Criando e Excluindo Arquivos

A biblioteca JCFIS permite a criação e exclusão de arquivos e diretórios. Primeiro, vamos trabalhar com arquivos. Vamos criar e imediatamente excluir o arquivo `New_file.txt`:

LOGGER.info("# Criando e excluindo um arquivo");
String fileName = "New_file.txt";
try (SmbFile file = new SmbFile("smb://192.168.56.101/publicshare/" + fileName, context)) {
    LOGGER.info("Prestes a criar o arquivo " + file.getName() + "!");
    file.createNewFile();

    LOGGER.info("Prestes a excluir o arquivo " + file.getName() + "!");
    file.delete();
}

Criamos um objeto `SmbFile` para um arquivo ainda não existente. Em seguida, chamamos seu método `createNewFile()`. Finalmente, aplicamos a função `delete()` para remover o arquivo. Notavelmente, `createNewFile()` ignora arquivos existentes sem notificação.

6.3. Criando e Excluindo Pastas

Podemos lidar com pastas de maneira semelhante:

LOGGER.info("# Criando e excluindo uma pasta");
String newFolderName = "New_folder/";
try (SmbFile newFolder = new SmbFile("smb://192.168.56.101/publicshare/" + newFolderName, context)) {
    LOGGER.info("Prestes a criar a pasta " + newFolder.getName() + "!");
    newFolder.mkdir();

    LOGGER.info("Prestes a excluir a pasta " + newFolder.getName() + "!");
    newFolder.delete();
}

Usamos o método `mkdir()` para criar a pasta e o método `delete()` para removê-la. No caso da pasta, devemos garantir que a pasta não exista; caso contrário, `mkdir()` falhará.

👀 Vamos notar que devemos ter muito cuidado ao remover uma pasta com `delete()`. Este método percorre e exclui toda a árvore de pastas, com todos os arquivos. Além disso, ele é capaz de remover a permissão somente leitura em arquivos.

Além disso, podemos criar uma árvore de diretórios inteira com o método `mkdirs()`:

LOGGER.info("# Criando e excluindo uma subpasta com pai");
newFolderName = "New_folder/";
String subFolderName = "New_subfolder/";
try (SmbFile newSubFolder = new SmbFile("smb://192.168.56.101/publicshare/" + newFolderName + subFolderName, context)) {
    LOGGER.info("Prestes a criar a pasta " + newSubFolder.getName() + "!");
    newSubFolder.mkdirs();
}

Criamos um novo diretório, `New_subfolder`, juntamente com a pasta pai anteriormente inexistente, `New_folder`.

6.4. Copiando Arquivos

O método `copyTo()` facilita a cópia de arquivos e diretórios. Podemos usá-lo em um único arquivo ou em uma pasta. Vamos copiar todo o conteúdo do `sambashare` para o `publicshare`:

LOGGER.info("# Copiando arquivos com copyTo");
try (SmbFile source = new SmbFile("smb://192.168.56.101/sambashare/", authContext); //precisa de autenticação
    SmbFile dest = new SmbFile("smb://192.168.56.101/publicshare/", context)) { //compartilhamento público
    source.copyTo(dest);
}

Copiamos chamando `copyTo()` no recurso Samba de origem e passando o recurso de destino `dest` para este método. Notavelmente, esses recursos são compartilhamentos Samba diferentes.

Também podemos copiar arquivos entre servidores diferentes. No entanto, não podemos copiar do sistema de arquivos local, apenas entre recursos gerenciados pelo Samba.


7. Trabalhando com Fluxos (Streams)

🔄 A biblioteca fornece `SmbFileInputStream` e `SmbFileOutputStream`, que substituem as classes abstratas padrão `InputStream` e `OutputStream` do Java, respectivamente. Vamos copiar um arquivo local para o compartilhamento Samba:

LOGGER.info("# Copiando arquivos com fluxos");
try (InputStream is = new FileInputStream("/home/joe/test.txt"); //Arquivo local
     SmbFile dest = new SmbFile("smb://192.168.56.101/publicshare/test_copy.txt", context); //Recurso Samba
     OutputStream os = dest.getOutputStream()) {

    byte[] buffer = new byte[65536]; // usando buffer de 64KB
    int bytesRead;
    while ((bytesRead = is.read(buffer)) != -1) {
        os.write(buffer, 0, bytesRead);
    }
}

Lemos o arquivo local com `FileInputStream`. Em seguida, copiamos o conteúdo usando um buffer interno. Este método complementa o método `copyTo()` quando arquivos locais estão em jogo.


8. Conclusão

🎯 Neste artigo, aprendemos como acessar recursos Samba com a biblioteca JCIFS. Para testes, configuramos um servidor Samba simples. Em seguida, examinamos um recurso compartilhado e aprendemos brevemente sobre autenticação Samba.

Depois, focamos nas operações de arquivos. Primeiro, listamos arquivos e pastas e verificamos suas propriedades. Em seguida, realizamos operações de criação, cópia e exclusão em arquivos e diretórios. Finalmente, usamos a implementação JCIFS dos fluxos de E/S do Java para ler e escrever arquivos Samba.

Como sempre, o código para os exemplos está disponível no GitHub.

📝 Mapeamento para String com MapStruct: Convertendo Enums, Datas e Objetos em Java

1. Visão Geral

Ao trabalhar com aplicações Java, muitas vezes precisamos converter objetos de dados complexos em representações mais simples. Por exemplo, é comum converter tipos de dados como enums, números ou objetos aninhados para seus equivalentes em String para exibição, registro em log (logging) ou respostas de API. Nesse cenário, podemos usar o MapStruct.

Neste tutorial, vamos mapear diferentes tipos de dados para uma String.


2. Configuração do Projeto

Para demonstrar o mapeamento para String no MapStruct, podemos criar um projeto Maven simples mapstructstringmapping.

No arquivo pom.xml, vamos navegar até o diretório mapstructstringmapping e atualizar:

<dependencies>
    <!-- MapStruct -->
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>1.6.3</version>
    </dependency>

    <!-- JUnit 5 -->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter</artifactId>
        <version>5.14.2</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Acima, adicionamos mapstruct para mapeamento em tempo de compilação e JUnit 5 para testes.


3. Mapeamento Simples para String

Ao trabalhar em apresentações ou mesmo em respostas de API, podemos precisar converter valores numéricos ou booleanos em strings. Um bom exemplo é quando uma entidade de banco de dados armazena a idade de um usuário como um int, mas a camada de API precisa expô-la como uma String.

Vamos examinar um exemplo direto para mostrar como usar o MapStruct para mapear um campo int para uma String. Primeiro, definimos a classe Person:

public class Person {
    private String name;
    private int age;
}

Em seguida, vamos criar a segunda classe PersonDTO:

public class PersonDTO {
    private String name;
    private String age;
}

Nos exemplos acima, as classes possuem getters e setters padrão, que o MapStruct utilizará para o mapeamento.

Agora, vamos definir a interface do mapper PersonMapper.java:

@Mapper
public interface PersonMapper {

    PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);
    PersonDTO toDTO(Person person);
}

Em tempo de compilação, o MapStruct cria a implementação de PersonMapper. Neste caso, o MapStruct automaticamente altera o valor int de age do objeto de origem para uma String no objeto de destino quando o método toDTO() é chamado.

Vamos criar o teste unitário PersonMapperUnitTest.java e garantir que o mapeamento funciona como pretendido:

public class PersonMapperUnitTest {

    @Test
    void givenPerson_whenMapsToPersonDTO_thenFieldsAreCorrect() {

        Person person = new Person();
        person.setName("Alice");
        person.setAge(30);

        PersonDTO dto = PersonMapper.INSTANCE.toDTO(person);

        assertEquals("Alice", dto.getName());
        assertEquals("30", dto.getAge());
    }
}

O teste confirma que o valor int da idade é traduzido para sua representação em String e que o campo name é mapeado com sucesso.


4. Conversão de Enums para String

Em Java, enums são amplamente usados para definir conjuntos fixos de variáveis, incluindo funções de usuário, status de pedidos e estados do sistema. No entanto, quando os dados são mostrados em interfaces do usuário ou tornados acessíveis através de APIs, esses valores de enum geralmente são renderizados como strings.

4.1. Definindo o Enum e as Classes de Domínio

Vamos começar definindo um enum que representa o status de um usuário:

public enum Status {
    ACTIVE,
    INACTIVE,
    PENDING
}

Para seguir em frente, vamos criar um objeto de domínio que usa este enum:

public class User {
    private String username;
    private Status status;
}

Por fim, criamos um DTO onde o valor do enum é representado como uma String:

public class UserDTO {
    private String username;
    private String status;
}

Agora, a classe User usa um enum para o campo status, enquanto UserDTO espera o mesmo valor como uma String.

4.2. Definindo o Mapper

Vamos definir uma interface de mapper que converte um User em um UserDTO:

@Mapper
public interface UserMapper {

    UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);

    UserDTO toDto(User user);
}

Aqui, o MapStruct detecta automaticamente que o campo de origem é um enum e o campo de destino é uma String. Não precisamos definir nenhuma lógica de mapeamento personalizada. Ele invoca o método name() do enum durante o processo de mapeamento.

Na maioria das APIs do mundo real, esse comportamento padrão é suficiente, mas é importante estar ciente disso se os nomes dos enums não corresponderem aos valores esperados pelos clientes.

4.3. Verificando o Mapeamento

Vamos escrever um teste unitário que confirma que a conversão de enum para string funciona conforme o esperado:

public class UserMapperUnitTest {

    @Test
    void shouldMapEnumToString() {

        User user = new User();
        user.setUsername("Kevin");
        user.setStatus(Status.ACTIVE);

        UserDTO dto = UserMapper.INSTANCE.toDto(user);

        assertEquals("Kevin", dto.getUsername());
        assertEquals("ACTIVE", dto.getStatus());
    }
}

Isto é o que o teste verifica:

  • O campo username é mapeado corretamente
  • O valor do enum Status.ACTIVE é convertido para sua representação em String, “ACTIVE”

Notavelmente, este comportamento funciona "pronto para uso" com MapStruct e não requer configuração adicional.


5. Mapeando Datas para String

Ao trabalhar com campos de data, muitas vezes precisamos convertê-los em representações de string formatadas antes de expô-los através de APIs ou exibi-los em interfaces do usuário. O MapStruct suporta este caso de uso através do atributo dateFormat na anotação @Mapping.

Usando este atributo, podemos definir o padrão de data exato que queremos que o MapStruct aplique durante o processo de mapeamento.

5.1. Definindo as Classes de Domínio e DTO

Vamos começar definindo uma entidade de domínio simples que contém um campo LocalDate:

public class Event {
    private String name;
    private LocalDate eventDate;
}

Em seguida, vamos definir um DTO correspondente onde o campo eventDate é representado como uma String:

public class EventDTO {
    private String name;
    private String eventDate;
}

Aqui, a classe Event representa o modelo de domínio, enquanto EventDTO é o objeto de transferência de dados usado para saída. A diferença principal é que o campo eventDate é um LocalDate no objeto de origem e uma String formatada no objeto de destino.

5.2. Criando o Mapper

Agora, vamos definir uma interface de mapper para converter um Event em um EventDTO:

@Mapper
public interface EventMapper {

    EventMapper INSTANCE = Mappers.getMapper(EventMapper.class);

    @Mapping(source = "eventDate", target = "eventDate", dateFormat = "yyyy-MM-dd")
    EventDTO toEventDTO(Event event);
}

Aqui, @Mapping especifica que o campo eventDate deve ser formatado de acordo com o padrão "yyyy-MM-dd" (por exemplo, "2024-12-31"). O MapStruct cuida da conversão do objeto LocalDate para a representação de string correspondente.

5.3. Testando a Conversão de Data

Para garantir que o mapeamento e a formatação funcionam corretamente, podemos escrever um teste unitário:

public class EventMapperUnitTest {

    @Test
    void shouldMapLocalDateToStringUsingProvidedFormat() {

        Event event = new Event();
        event.setName("Conferência");
        event.setEventDate(LocalDate.of(2024, 12, 31));

        EventDTO dto = EventMapper.INSTANCE.toEventDTO(event);

        assertEquals("Conferência", dto.getName());
        assertEquals("2024-12-31", dto.getEventDate());
    }
}

O teste acima confirma que:

  • O campo name é mapeado sem alterações
  • O objeto LocalDate é formatado corretamente no padrão especificado "yyyy-MM-dd"

O uso do atributo dateFormat é particularmente útil para garantir a consistência dos formatos de data em diferentes pontos de extremidade da API ou componentes da interface do usuário.


6. Considerações Adicionais e Melhores Práticas

Lidando com Valores Nulos

Em cenários do mundo real, os dados de origem podem conter valores nulos. O MapStruct lida com eles de forma segura por padrão, mas é importante testar e documentar o comportamento esperado em seus mapeadores.

Customizando Conversões Complexas

Para cenários mais complexos (por exemplo, formatar números com casas decimais específicas, converter objetos aninhados em strings JSON), você pode usar métodos default dentro da interface do mapper ou definir um método de mapeamento personalizado usando a anotação @Named.

Testes Abrangentes

Sempre escreva testes para seus mapeadores, cobrindo casos de uso comuns, casos de borda (valores nulos, enums desconhecidos) e formatos específicos. Isso garante que as conversões de dados permaneçam confiáveis conforme sua aplicação evolui.


7. Conclusão

Neste tutorial, exploramos como usar o MapStruct para mapear vários tipos de dados para suas representações em String. Vimos como o mapeamento direto de tipos primitivos como int funciona automaticamente, como converter valores de enum usando o método name() e como formatar objetos LocalDate usando o atributo dateFormat na anotação @Mapping.

💡 O MapStruct simplifica significativamente a conversão de dados em aplicações Java, fornecendo mapeamento seguro de tipos em tempo de compilação. Ao utilizar esses padrões, podemos manter nosso código limpo, legível e fácil de manter ao lidar com diferentes representações de dados em nossas aplicações.

quinta-feira, 22 de janeiro de 2026

🔍 Visualizando o Código-Fonte de um Arquivo .class do Java: Como Descompilar Bytecode

🔍 Visualizando o Código-Fonte de um Arquivo .class do Java

No mundo Java, o código-fonte escrito em arquivos .java é compilado para um formato intermediário chamado bytecode, armazenado em arquivos com extensão .class. Esses arquivos não contêm o código-fonte original legível, mas instruções para a Java Virtual Machine (JVM). Então, como podemos "visualizar" o código original a partir de um arquivo .class? A resposta está na descompilação – processo de reconstruir o código-fonte a partir do bytecode.


🧠 O Que é Bytecode e Por Que Precisamos Descompilar?

O bytecode é uma representação compacta e otimizada do seu programa, projetada para ser executada pela JVM. Ele não é destinado à leitura humana. No entanto, situações como análise de bibliotecas de terceiros, debugging de problemas complexos, estudos de código legado sem fonte disponível ou até recuperação de código perdido podem exigir que você visualize algo próximo ao código original. É importante ressaltar que a descompilação para fins de engenharia reversa deve respeitar os termos de licença do software e os direitos autorais.


🛠️ Ferramentas Populares para Descompilar Arquivos .class

Existem várias ferramentas robustas que convertem bytecode Java em código legível. Aqui estão as principais:

1. JD-GUI

Uma ferramenta gráfica gratuita que permite abrir arquivos .class ou .jar e navegar pela estrutura descompilada como se fosse um projeto. Ela fornece uma visualização limpa e imediata, sendo excelente para análises rápidas.

2. Bytecode Viewer

Uma ferramenta mais avançada que mostra não apenas o código descompilado (usando motores como CFR, FernFlower ou Procyon), mas também o bytecode real e o código em hexa. É ideal para desenvolvedores que querem entender a relação entre o código-fonte e as instruções da JVM.

3. CFR

É um descompilador moderno e de alta qualidade, disponível como biblioteca ou via linha de comando. Ele lida bem com recursos mais novos da linguagem, como lambdas e switch expressions, gerando um código reconstruído muito fiel.


📝 Passo a Passo Prático com JD-GUI

  1. Baixe e execute o JD-GUI a partir do site oficial.
  2. Abra seu arquivo .class ou .jar através do menu "File > Open File...".
  3. Navegue pela árvore do projeto no lado esquerdo. Ao clicar em uma classe, o código descompilado aparecerá no painel principal.
  4. Exporte o código se necessário, usando "File > Save All Sources".

⚠️ Limitações e Considerações Importantes

A descompilação não é uma mágica perfeita. Nomes de variáveis locais são perdidos, sendo substituídos por nomes genéricos (var1, var2). Comentários e formatação original são completamente removidos. Estruturas como laços for-each podem aparecer como iteradores tradicionais. Além disso, código ofuscado propositalmente pode gerar uma saída ilegível. Do ponto de vista legal, usar código descompilado para criar uma obra derivada sem permissão viola licenças de software.


🔧 Visualizando Bytecode Puro (javap)

Às vezes, você não quer o código reconstruído, mas sim inspecionar as instruções reais do bytecode. Para isso, use a ferramenta javap, que vem com o JDK. Execute no terminal: javap -c -p NomeDaClasse.class. A flag -c exibe as instruções bytecode e -p mostra membros privados. É uma análise de baixo nível valiosa para otimização ou debugging profundo.


🎯 Conclusão

Descompilar arquivos .class é uma habilidade útil no arsenal de qualquer desenvolvedor Java, seja para aprender, solucionar problemas ou analisar dependências. Ferramentas como JD-GUI e Bytecode Viewer tornam o processo acessível. No entanto, use esse conhecimento com responsabilidade ética e legal, sempre respeitando a propriedade intelectual. Lembre-se: a descompilação é uma ferramenta de análise, não de cópia. Dominar tanto o código-fonte quanto o bytecode amplia significativamente sua compreensão da plataforma Java.

segunda-feira, 5 de janeiro de 2026

🚀 Java 25: O Que Esperar da Próxima Grande Versão da Plataforma Java?

Java 25: Olhando Para o Horizonte da Plataforma

O mundo do desenvolvimento Java está sempre em evolução, e a comunidade já começa a especular e acompanhar os primeiros indícios do que será o JDK 25. Seguindo o ciclo de lançamentos semestrais estabelecido pela Oracle, o Java 25 promete trazer novas features, melhorias de performance e refinamentos nas APIs que sustentam milhões de aplicações em todo o mundo. Neste post, exploramos o que se pode esperar desta versão, baseado no processo de desenvolvimento aberto do OpenJDK.


📅 O Ciclo de Lançamentos e o Roadmap do JDK 25

Com o modelo de lançamento rápido (six-month release cadence), o Java 25 está previsto para ser lançado em março de 2025, como sucessor do JDK 24. É crucial entender que, nesta fase, as funcionalidades ainda estão em proposta e desenvolvimento ativo no Project Amber, Project Valhalla, Project Loom e outros incubator modules. As JEPs (JDK Enhancement Proposals) que integrarão oficialmente a versão 25 serão definidas e priorizadas ao longo dos próximos meses pela comunidade de desenvolvedores.


🔍 Possíveis Recursos e Melhorias em Discussão

Embora a lista final de JEPs para o Java 25 ainda não esteva fechada, podemos olhar para as propostas em estágio de preview, incubação ou discussão ativa nas versões anteriores (JDK 21 ao 24) para prever o que pode amadurecer e ser promovido. Algumas áreas de interesse incluem:

Continuidade das Inovações em Concorrência e Modelo de Threads

Os Virtual Threads (Project Loom), lançados de forma definitiva no Java 21, continuam recebendo refinamentos. No JDK 25, é possível esperar otimizações adicionais na performance, debugging e integração com frameworks e bibliotecas do ecossistema, consolidando ainda mais este modelo revolucionário para lidar com concorrência.

Evolução do Sistema de Tipos e Modelo de Memória

O Project Valhalla, que busca introduzir value objects e classes primitivas especializadas, pode dar mais um passo significativo. A introdução de primitive classes em estágio preview é uma possibilidade concreta, prometendo melhorias dramáticas de performance e uso de memória para tipos de dados simples.

Refinamentos na Sintaxe (Project Amber)

O Project Amber tem sido responsável por tornar o Java mais conciso e expressivo. Constructos como pattern matching para switch e registros (records) podem ganhar novas capacidades, como padrões aninhados mais poderosos ou a evolução dos sealed classes.


⚙️ Impacto para Desenvolvedores e Empresas

A adoção do Java 25, como qualquer nova versão, deve ser planejada. A boa notícia é que o modelo de lançamento semestral com LTS (Long-Term Support) a cada seis versões (sendo a próxima LTS o Java 27) oferece flexibilidade. Desenvolvedores podem testar as novas features em estágio preview sem comprometer a estabilidade de produção. Manter-se atualizado com as versões não-LTS, como a 25, permite experimentar inovações rapidamente, preparando a base de código para a futura migração para uma versão LTS.


🔧 Como Acompanhar o Desenvolvimento do Java 25

Para ficar por dentro das novidades em tempo real, a melhor fonte é o site oficial do OpenJDK. Lá você pode acompanhar o painel de JEPs destinadas ao JDK 25, acessar builds early-access e participar de listas de discussão. Outro canal valioso são as comunidades Java, como a Java Community Process (JCP) e fóruns de desenvolvedores, onde as propostas são debatidas.


🎯 Conclusão: Preparando-se para o Futuro

O Java 25 representa mais um capítulo na contínua modernização de uma das plataformas de desenvolvimento mais críticas do mundo. Embora suas features definitivas ainda estejam se moldando, uma coisa é certa: a linguagem continua evoluindo com foco em produtividade, performance e segurança. Para o desenvolvedor Java, acompanhar essas mudanças não é só sobre aprender uma nova sintaxe, mas sobre compreender as novas abstrações e paradigmas que estarão disponíveis para construir a próxima geração de aplicações escaláveis, eficientes e robustas. Fique de olho nas prévias e comece seus testes!

🔧 Como Usar Condicionais If/Else em Makefiles no Linux – Guia Prático

🔧 Introdução a Condicionais em Makefiles

Makefiles são ferramentas essenciais para automação de compilação em ambientes Linux, permitindo definir regras e dependências para construção de projetos. Um dos recursos mais poderosos, porém menos explorados por iniciantes, é o uso de condicionais if/else. Eles permitem tomar decisões dinâmicas durante o processo de build, adaptando-se a diferentes ambientes, arquiteturas ou parâmetros fornecidos pelo usuário.


📝 Sintaxe Básica dos Condicionais

A estrutura condicional em um Makefile segue uma lógica específica, diferente de linguagens de programação convencionais. Ela é baseada em diretivas que são avaliadas durante a fase de leitura do Makefile, antes da execução das regras.


⚙️ A Estrutura ifeq e ifneq

A diretiva ifeq (if equal) verifica se dois valores são idênticos. Sua forma básica é:

ifeq (arg1, arg2)
    # comandos se verdadeiro
else
    # comandos se falso
endif

Por exemplo, para verificar o sistema operacional alvo:

ifeq ($(OS),Linux)
    CC=gcc
else
    CC=clang
endif

Já a diretiva ifneq (if not equal) faz o inverso, executando o bloco se os argumentos forem diferentes.


🔎 Condicionais com ifdef e ifndef

Essas diretivas verificam se uma variável está definida (e não vazia) ou não. São extremamente úteis para flags opcionais.

ifdef DEBUG
    CFLAGS += -g -O0
else
    CFLAGS += -O2
endif

ifndef é seu complemento, ativando o bloco se a variável não estiver definida.


🚀 Exemplo Prático: Compilação Condicional

Vamos criar um exemplo real. Suponha um projeto que pode ser compilado para produção (release) ou desenvolvimento (debug).

# Defina TARGET=debug para habilitar modo de depuração
TARGET ?= release

ifeq ($(TARGET), debug)
    CFLAGS = -Wall -g -DDEBUG
    BIN_NAME = meuapp_debug
else
    CFLAGS = -Wall -O3
    BIN_NAME = meuapp
endif

todos: $(BIN_NAME)

$(BIN_NAME): main.c
    $(CC) $(CFLAGS) -o $@ $^

Ao executar make TARGET=debug, o Makefile usará as flags de depuração. O comando simples make usará a configuração otimizada de release.


⚠️ Pontos de Atenção e Boas Práticas

1. Avaliação Imediata: Os condicionais são avaliados no momento da leitura do Makefile, não durante a execução das regras. Variáveis definidas dentro de comandos de regra não afetam condicionais superiores.

2. Espaçamento: A sintaxe é sensível a espaços. Não adicione espaços após as vírgulas nos argumentos de ifeq.

3. Combine com Funções: Use funções como $(filter) ou $(findstring) dentro de condicionais para lógicas mais complexas.


🎯 Conclusão

Dominar condicionais if/else em Makefiles é um passo fundamental para criar sistemas de build robustos e flexíveis no Linux. Eles permitem adaptar a compilação a múltiplos cenários, tornando seu projeto mais portátil e fácil de manter. Comece com exemplos simples, como a escolha entre debug/release, e gradualmente incorpore condições mais complexas para gerenciar dependências ou diferentes plataformas de destino.

quarta-feira, 8 de setembro de 2021

🚀 Apresentando o Java SE 10

🚀 Apresentando o Java SE 10

Nos últimos 22 anos, o Java cresceu até se tornar uma comunidade vibrante que atingiu uma escala sem igual. O Java continua a trazer valor para desenvolvedores e empresas em todo o mundo. Um planejamento cuidadoso e o envolvimento do ecossistema ajudaram o Java a se tornar uma das linguagens de programação mais usadas do planeta. Com mais de 12 milhões de desenvolvedores em todo o mundo executando Java, ele continua sendo a linguagem de programação número 1 escolhida por programadores de software. Daqui para frente, o objetivo é garantir que o Java esteja bem posicionado para o desenvolvimento moderno e o crescimento na nuvem.


Em 2017, foi anunciada a intenção de mudar para um novo ciclo de lançamentos de seis meses para o Java, com o objetivo de reduzir a latência entre os lançamentos principais. Ao mesmo tempo, foram anunciados os planos para construir e distribuir binários do OpenJDK. Este modelo de lançamento é inspirado nos modelos de lançamento usados por outras plataformas e por várias distribuições de sistemas operacionais, atendendo ao cenário moderno de desenvolvimento de aplicativos. O ritmo da inovação está acontecendo em uma taxa cada vez maior, e este novo modelo de lançamento permitirá que os desenvolvedores aproveitem novos recursos em produção o mais rápido possível. O desenvolvimento moderno de aplicativos espera um licenciamento aberto simples e um ritmo previsível baseado no tempo, e o novo modelo de lançamento atende a ambos.


Com isso, temos o prazer de anunciar a disponibilidade geral do Java 10, o primeiro lançamento com prazo definido como parte do novo ciclo de lançamentos de seis meses. Esta versão é mais do que uma simples correção de estabilidade e desempenho em relação ao Java SE 9; na verdade, ela introduz doze novos aprimoramentos definidos através das JDK Enhancement Proposals (JEPs) que os desenvolvedores podem começar a usar imediatamente:

⚙️ Principais Aprimoramentos (JEPs)

  • (JEP 286) Inferência de Tipo para Variáveis Locais: Estende a inferência de tipo para declarações de variáveis locais com inicializadores. Ele introduz
    var
    no Java, algo comum em outras linguagens.
  • (JEP 296) Consolidar a Floresta JDK em um Único Repositório: Combina os numerosos repositórios da floresta JDK em um único repositório para simplificar e agilizar o desenvolvimento.
  • (JEP 204) Interface do Coletor de Lixo: Melhora o isolamento do código-fonte de diferentes coletores de lixo, introduzindo uma interface de coletor de lixo (GC) limpa.
  • (JEP 307) GC Completo Paralelo para o G1: Melhora as latências do pior caso do G1 tornando a coleta de lixo (GC) completa paralela.
  • (JEP 301) Compartilhamento de Dados de Classe de Aplicativo: Para melhorar a inicialização e a pegada de memória, estende o recurso existente de Compartilhamento de Dados de Classe ("CDS") para permitir que classes de aplicativo sejam colocadas no arquivo compartilhado.
  • (JEP 312) Aperto de Mãos Local por Thread: Introduz uma maneira de executar um callback em threads sem executar um ponto seguro global da VM. Torna possível e barato parar threads individuais, e não apenas todos os threads ou nenhum.
  • (JEP 313) Remover a Ferramenta Geradora de Cabeçalho Nativo: Remove a ferramenta
    javah
    do JDK, uma vez que ela foi superada por funcionalidades superiores no
    javac
    .
  • (JEP 314) Extensões Adicionais de Tag de Idioma Unicode: Aprimora
    java.util.Locale
    e APIs relacionadas para implementar extensões Unicode adicionais de tags de idioma BCP 47.
  • (JEP 316) Alocação de Heap em Dispositivos de Memória Alternativos: Permite que a HotSpot VM aloque o heap de objetos Java em um dispositivo de memória alternativo, como um NV-DIMM, especificado pelo usuário.
  • (JEP 317) Compilador JIT Experimental Baseado em Java: Permite que o compilador JIT baseado em Java, Graal, seja usado como um compilador JIT experimental na plataforma Linux/x64.
  • (JEP 319) Certificados Raiz: Fornece um conjunto padrão de certificados de Autoridade de Certificação (CA) raiz no JDK.
  • (JEP 322) Versionamento de Lançamento Baseado em Tempo: Revisa o esquema da string de versão da Plataforma Java SE e do JDK, e informações de versionamento relacionadas, para os modelos de lançamento baseados em tempo atuais e futuros.

🌍 O Ecossistema Java

O ecossistema Java continua a ser uma coleção diversificada de desenvolvedores e sua participação contínua é bem-vinda para ajudar a moldar o futuro do Java.

🔍 Diagnosticando TLS, SSL e HTTPS em Aplicações Java

Diagnosticando TLS, SSL e HTTPS

Ao construir aplicações interconectadas, desenvolvedores frequentemente interagem com protocolos habilitados para TLS, como HTTPS. Com a recente ênfase em comunicações criptografadas, este conteúdo aborda a forma como o JDK evolui em relação a protocolos, algoritmos e alterações, bem como alguns diagnósticos avançados para entender melhor conexões TLS como HTTPS.

A maioria dos desenvolvedores não precisará fazer esse nível de diagnóstico no processo de escrita ou execução de aplicações. No entanto, se necessário, as informações a seguir devem fornecer base suficiente para entender o que está acontecendo dentro de conexões seguras.


Evolução de protocolos e algoritmos

Nos últimos 15 anos, a plataforma Java evoluiu por meio do Java Community Process, onde empresas, organizações e indivíduos dedicados desenvolvem e votam em especificações para determinar o que compõe a Plataforma Java. Grande parte dos esforços está centrada na compatibilidade, como o TCK, garantindo que diferentes implementações sejam compatíveis entre si e que os desenvolvedores possam prever como suas aplicações serão executadas. Opções padrão críticas (como o protocolo TLS) não são alteradas dentro de versões menores.

A tabela a seguir descreve os protocolos e algoritmos suportados em cada versão do JDK:

JDK 8 (Março 2014 - presente) JDK 7 (Julho 2011 - presente) JDK 6 (2006 até fim das atualizações públicas 2013)
Protocolos TLS: TLSv1.2 (padrão)
TLSv1.1
TLSv1
SSLv3
Protocolos TLS: TLSv1.2
TLSv1.1
TLSv1 (padrão)
SSLv3
Protocolos TLS: TLSv1.2 (atualização 111+)
TLSv1.1 (atualização 111+)
TLSv1 (padrão)
SSLv3
Cifras JSSE: Cifras no JDK 8 Cifras JSSE: Cifras no JDK 7 Cifras JSSE: Cifras no JDK 6

📝 Código Java de exemplo para fazer uma conexão HTTPS

Fazer uma conexão HTTPS em Java é relativamente simples. O código é apresentado com foco no ajuste e na compreensão das capacidades subjacentes.

Código de back-end de exemplo para fazer uma conexão SSL:

final URL url = new URL("https://example.com");
try(final InputStream in = url.openStream()){
  //…
}

A conexão também pode ser ajustada através de um cast:

final HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
//opera em conn
conn.connect();
try(final InputStream in = conn.getInputStream()){
  //…
}

Exemplo: Página "View My Client" do Qualys SSL Labs

O Qualys SSL Labs mantém uma coleção de ferramentas úteis para entender conexões SSL/TLS. Uma em particular é a página "View My Client", que exibe informações sobre a conexão do cliente. Ao integrar com essa página, é possível controlar a implementação enquanto se usam diferentes parâmetros de ajuste do Java.

Para testar o ajuste de parâmetros, foi implementada uma pequena aplicação JavaFX em JavaScript. Ela exibe essa página em um WebView, mostrando informações sobre a conexão cliente SSL/TLS subjacente do Java. O código pode ser encontrado no apêndice.


🔧 Parâmetros de ajuste do JSSE

Ao diagnosticar problemas relacionados a TLS, há várias propriedades do sistema úteis. Elas geralmente são abordadas em suas seções relevantes do JSSE, mas esta coleção única pode ajudar quem busca entender a flexibilidade da implementação do Java ou diagnosticar detalhes de conexão.

Parâmetro Descrição
javax.net.debug Imprime detalhes de depuração para conexões feitas.
Exemplo: -Djavax.net.debug=all ou -Djavax.net.debug=ssl:handshake:verbose
https.protocols Controla a versão do protocolo usada por clientes Java que obtêm conexões https através do uso da classe HttpsURLConnection ou via operações URL.openStream(). Para versões mais antigas, isso pode atualizar o padrão, caso seu cliente Java 7 queira usar TLS 1.2 como padrão.
Exemplo: -Dhttps.protocols=TLSv1,TLSv1.1,TLSv1.2
Para protocolos não HTTP, isso pode ser controlado através do SSLContext do SocketFactory.
jdk.tls.client.protocols Controla a implementação TLS subjacente da plataforma. Mais informações estão disponíveis no Guia de Referência do JSSE.
Exemplo: -Djdk.tls.client.protocols=TLSv1.1,TLSv1.2
Disponível em todas as versões do JDK 8, ou após Java 7 update 95 (Janeiro 2016) e Java 6 update 121 (Julho 2016).
http.agent Ao iniciar conexões, o Java aplica isso como sua string de agente do usuário. Modificar isso resolve casos onde a parte receptora responde de forma diferente com base no agente do usuário.
Exemplo: -Dhttp.agent=“agente conhecido”
java.net.useSystemProxies Usa detalhes de proxy do próprio sistema operacional.
Exemplo: -Djava.net.useSystemProxies=true
http.proxyHost
http.proxyPort
A conexão de proxy a ser usada para conexões HTTP.
Exemplo: -Dhttp.proxyHost=proxy.exemplo.com -Dhttp.proxyPort=8080
https.proxyHost
https.proxyPort
O mesmo que acima, exceto que a configuração é separada entre HTTP e HTTPS.
http.proxyUser
http.proxyPassword
https.proxyUser
https.proxyPassword
Credenciais baseadas em senha para os proxies acima.

🔎 Exemplo de diagnóstico de um problema

Ao fazer uma conexão HTTPS, suponha que o cliente lançou a seguinte exceção devido a um handshake falho com o servidor:

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

SSLHandshakeException é uma subclasse de IOException, então não é necessário capturá-la explicitamente. A maioria dos desenvolvedores não precisará de uma captura explícita, mas isso pode ajudar a diagnosticar mais facilmente a causa de qualquer IOException.

Ao aplicar a propriedade -Djavax.net.debug=all, a falha associada a esta SSLHandshakeException apareceria logo após a negociação de algoritmo nos logs.

JDK 7 (falha em algoritmo não suportado) JDK 8 (funciona bem)
Cipher Suites: […Lista longa de cifras…]
Compression Methods: { 0 }
Extension elliptic_curves, curve names: {…}
Extension ec_point_formats, formats: [uncompressed]
Extension server_name, server_name: [host_name: HOST]
main, WRITE: TLSv1 Handshake, length = 168
main, READ: TLSv1 Alert, length = 2
main, RECV TLSv1 ALERT: fatal, handshake_failure
main, called closeSocket()
main, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
Cipher Suites: […Lista longa de cifras…]
Compression Methods: { 0 }
Extension elliptic_curves, curve names: {…}
Extension ec_point_formats, formats: [uncompressed]
Extension signature_algorithms, signature_algorithms: …
Extension server_name, server_name: [type=host_name (0), value=HOST]
main, WRITE: TLSv1.2 Handshake, length = 226
main, READ: TLSv1.2 Handshake, length = 89
*** ServerHello, TLSv1.2
RandomCookie: GMT: -1809079139 bytes = { …}
Session ID: {…}
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
Compression Method: 0
Extension renegotiation_info, renegotiated_connection: <empty>
Extension ec_point_formats, formats: [uncompressed, ansiX962_compressed_prime, ansiX962_compressed_char2]
%% Initialized: [Session-1, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256]
** TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
main, READ: TLSv1.2 Handshake, length = 2308

No caso acima, a falha ocorreu durante o handshake. A causa mais provável para isso é o suporte de algoritmo. O JDK fornece um pacote separado chamado JCE Força Ilimitada, projetado para adicionar suporte a algoritmos mais fortes do que o disponível por padrão. O Qualys SSL Labs fornece um teste de servidor SSL diferente que enumerará quais algoritmos um servidor suporta.


Adicionando algoritmos mais fortes: JCE Força Ilimitada

Em um ambiente de alta segurança, uma forma de fortalecer os algoritmos no JDK é através dos arquivos de política JCE Força Ilimitada. Neste caso específico, substituir esses arquivos de política dentro do JDK 7 permite que ele use as variantes mais fortes dos algoritmos existentes e se conecte com sucesso.


Apêndice

O código a seguir abrirá a página "View My Client" do Qualys SSL Labs dentro de um cliente Java. Para testar configurações, execute assim:

jjs -fx viewmyclient.js
jjs -fx -Dhttps.protocols=TLSv1 viewmyclient.js
var Scene = javafx.scene.Scene;
var WebView = javafx.scene.web.WebView;
var browser = new WebView();
browser.getEngine().load("https://ssllabs.com/ssltest/viewMyClient.html");
$STAGE.scene = new Scene(browser);
$STAGE.show();

🔄 Atualização e Perguntas Frequentes sobre o Ritmo de Lançamento do Java SE

🔄 Atualização e Perguntas Frequentes sobre o Ritmo de Lançamento do Java SE

No início de 2017, conforme o trabalho no Java SE 9 se aproximava do fim, alguns colaboradores da Comunidade OpenJDK começaram a se perguntar se haveria uma maneira de evoluir a Plataforma Java SE e o JDK em um ritmo mais acelerado, para que novos recursos pudessem ser entregues de maneira mais oportuna. Um grupo de trabalho do JCP foi estabelecido para considerar como o Java Community Process poderia acomodar tal mudança. Após mais discussões entre os principais colaboradores, um plano foi proposto e, em paralelo, foram anunciados planos para seus produtos comerciais Java SE.


Nos poucos meses desde então, a Comunidade OpenJDK, com a liderança da Oracle, entregou o Java SE 9, o Java SE 10, versões de Acesso Antecipado do Java SE 11, bem como múltiplas atualizações de segurança programadas e coordenadas. O OpenJDK Vulnerability Group foi formado. Um novo e pequeno recurso de linguagem foi adicionado no Java SE 10, o que mostra que o novo ritmo funciona não apenas para a implementação, mas também para o trabalho de especificação no JCP.


Dito isto, o novo ritmo introduz novos idiomas e semântica a termos e processos aos quais estamos acostumados há muitos anos. Claramente, os benefícios de um cronograma de lançamento previsível de novos recursos facilmente assimiláveis valem o esforço para alguns dos maiores projetos do ecossistema. Essa tendência também foi observada em outras partes do Ecossistema Java SE. Por exemplo, o Eclipse há muito tem um "trem de lançamento" anual, e o Wildfly está migrando para um modelo de lançamento trimestral.


❓ Pergunta 1: Certamente não se espera que todos adotem releases principais a cada seis meses?!

Não existem mais "releases principais" propriamente ditos; esse agora é um termo legado. Em vez disso, há um fluxo constante de "releases de recursos". Isso é consistente com a forma como muitos lançamentos foram feitos no passado, exceto com uma nova abordagem sobre o versionamento. Por exemplo, o Java 8 foi lançado em março de 2014. O 8u20, um release de recurso, foi lançado quase seis meses depois, em agosto. O 8u40, o próximo release de recurso, foi lançado quase seis meses depois disso.

Então sim, espera-se a adoção de "releases de recursos" a cada seis meses, assim como antes.

Passar do Java 9 para o 10 e para o 11 é mais parecido com passar de 8 para 8u20 e para 8u40 do que de 7 para 8 e para 9. É assustador ver isso a princípio quando se está acostumado a releases principais a cada três anos e se tem um modelo mental do grande impacto dessas grandes mudanças. O ritmo de seis meses não é isso. Mais adiante no FAQ, será fornecida uma prova mais específica disso.


❓ Pergunta 2: Se os novos lançamentos são basicamente o antigo ritmo de seis meses, por que atualizar o número da release principal cada vez? Por que não chamá-lo simplesmente de 9u20, 9u40, etc.?

Por ter simplificado alguns processos do JCP, agora é possível introduzir novos recursos de biblioteca de classes, JVM e linguagem, como a Inferência de Tipo de Variável Local, em apenas seis meses, em vez de ter que esperar anos por uma "release principal". Em vez de lançar dezenas de grandes mudanças nas especificações a cada dois anos, elas podem ser introduzidas de forma mais pragmática em um fluxo constante assim que estiverem prontas para adoção.


❓ Pergunta 3: Mudanças na especificação parecem perigosas e vão inibir o ecossistema de ferramentas de se atualizar, certo?

Embora algumas ferramentas tenham tido dificuldade para migrar de 8 para 9, foi fantástico ver aqueles que fizeram essa transição serem capazes de ir de 9 para 10 quase que da noite para o dia.

Quando o Java 10 foi lançado, todas as principais IDEs tinham suporte ao Java 10, incluindo o novo recurso de inferência de tipo de variável local em questão de dias. Projetos populares como Gradle e Lucene adicionaram rapidamente suporte oficial. Algumas distribuições populares do Linux, como Ubuntu e SUSE Linux Enterprise Server, ajustaram-se proativamente para tornar as últimas releases do OpenJDK o JRE/JDK padrão em suas plataformas. O Elasticsearch planeja ser compatível com releases LTS e não LTS o mais rápido possível para se beneficiar dos novos recursos. Estes são apenas alguns exemplos de outros projetos e produtos mantendo-se no ritmo de seis meses.

O novo ritmo torna mais gerenciável e previsível para os fornecedores de ferramentas, que agora terão um fluxo constante de atualizações menores. Além disso, desenvolvedores com visão de futuro podem explorar novos recursos em desenvolvimento, como tipos de valor mínimo do OpenJDK Project Valhalla ou o Z Garbage Collector do OpenJDK Project ZGC, usando versões de acesso antecipado disponíveis sob uma licença de código aberto familiar.


❓ Pergunta 4: Por que alguém atualizaria para a versão X quando uma nova release X+1 está a apenas seis meses de distância?

Os builds mais recentes do Oracle JDK e os builds do OpenJDK da Oracle são baixados milhões de vezes por mês por desenvolvedores. Foi observado um crescimento consistente nos downloads do JDK com cada release de recurso, incluindo o 9 e o 10. As releases mais recentes do Java 10 estão sendo baixadas a uma taxa muito maior do que as do Java 7 e Java 8 eram. Por exemplo, os downloads do JDK 10, no momento desta escrita, excedem os das atualizações do JDK 8 por um fator de cinco.

A forte adoção do novo ritmo de lançamento é impressionante. É muito encorajador ver IDEs populares e outros fornecedores de ferramentas adotarem e disponibilizarem suporte ao Java 10 rapidamente.


❓ Pergunta 5: Ainda não estou convencido. O Java 9 foi um desafio para adotar, então isso significa que o 10 e o 11 também serão.

Muitos desenvolvedores e usuários de Java SE historicamente esperaram por algumas atualizações antes de adotar uma nova "versão principal". Isso era esperado quando havia dezenas de novos recursos principais que alteravam a especificação em uma release "principal", mas não será o caso daqui para frente com os lançamentos de seis meses. Este não tem sido o caso desde o Java SE 9.

Por exemplo, a release do Java SE 9 incorporou aproximadamente 19.000 mudanças no código-fonte em relação ao Java SE 8. Houve apenas 2.700 dessas mudanças entre o Java 9 e o Java 10 – aproximadamente a mesma quantidade entre o Java 8 e o Java 8u40. Então, enquanto o Java SE 9 foi uma atualização "principal" comparado ao Java SE 8, já vimos que o Java SE 10 é uma simples atualização de recurso para o Java SE 9.


❓ Pergunta 6: Como posso ter confiança de que a transição para a release X+1 será tranquila? Quanto tempo há para a transição?

Os Builds de Acesso Antecipado (EA) estão ainda mais fáceis do que antes para baixar e testar, incluindo os próprios builds do OpenJDK da Oracle. A recomendação é que os desenvolvedores usem os builds de EA do OpenJDK da Oracle em seus sistemas de teste de construção para que quaisquer problemas possam ser detectados antecipadamente.

Há três meses entre a atualização final de uma release de recurso e a atualização de segurança da próxima release de recurso. A recomendação é fazer a transição durante esse período. Há aproximadamente um mês entre uma nova release de recurso e a próxima atualização de segurança programada. Por exemplo, o Java 9.0.4 foi lançado em janeiro de 2018, o Java 10.0.0 em março de 2018 e o 10.0.1 em abril de 2018. Após o lançamento do Java 10.0.1, não é recomendável usar o Java 9.0.4 ou o Java 10.0.0. No entanto, não é necessário esperar um mês, ou mesmo três meses, para começar a testar – os builds de Acesso Antecipado do JDK 10 foram publicados regularmente a partir de novembro de 2017, mais de seis meses antes da release de atualização 10.0.1.

Isso é consistente com os lançamentos históricos de recursos, onde houve 4-6 semanas entre os lançamentos de recursos e uma atualização de segurança subsequente. Por exemplo, o 8u40 foi lançado no início de março de 2015 e a subsequente atualização de segurança programada 8u45 foi lançada em 14 de abril de 2015.


❓ Pergunta 7: Ok, mas não quero novos recursos. Tenho um sistema em produção e só quero atualizações de estabilidade, desempenho e segurança. O que devo fazer?

A intenção é designar releases a cada três anos como releases de "Suporte de Longo Prazo" (LTS), começando com o Java SE 11 em setembro de 2018. Então, enquanto o Java SE 9 atingiu seu Fim de Vida com o lançamento do Java 10, e o Java 10 fará o mesmo com o lançamento do Java 11, o Java 11 terá suporte comercial da Oracle disponível por pelo menos oito anos adicionais.

Como aconteceu por quase uma década com o Java 6 e Java 7 (e provavelmente com o Java 8 em 2019), uma vez que a Oracle parar de contribuir com nossas alterações de código-fonte para uma série de releases específica no OpenJDK, para que possa focar nas necessidades de seus clientes, outros colaboradores qualificados na Comunidade OpenJDK podem intervir para continuar mantendo a série de releases. Eles fazem isso de acordo com os padrões da Comunidade OpenJDK pelo tempo que escolherem, fazendo o backport das mudanças relevantes de releases posteriores ainda mantidas pela Oracle e por outros. Por exemplo, para o JDK 6, a Sun estabeleceu o projeto em 2008, e a Oracle continuou a mantê-lo até 2013. Outros mantenedores então continuaram trabalhando no projeto fazendo backport de atualizações de releases posteriores.

A Oracle apoia essas transições na Comunidade OpenJDK fornecendo um processo estabelecido para que elas ocorram dentro do JDK Updates Project, bem como assistência a novos mantenedores para se estabelecerem em seus novos papéis, e, por último, mas não menos importante, o Vulnerability Group.


❓ Pergunta 8: O que está acontecendo com o Java SE 8?

O Java SE 8 é o fim do legado do modelo de versionamento e ritmo de lançamento; o Java 9 foi o novo começo.

Para o Oracle JDK, o Java 8 está passando exatamente pelos mesmos processos de transição do Java 7 e Java 6, com algumas exceções. Primeiro, para dar tempo adicional para se acostumar ao novo modelo de lançamento, a Oracle estendeu as atualizações públicas de seu Oracle JDK para janeiro de 2019 para uso comercial em produção, e pelo menos até o final de 2020 para uso individual em desktop. Segundo, foram anunciados esforços para tornar o Oracle JDK intercambiável com os builds do OpenJDK da Oracle para aqueles que desejam migrar para as próximas releases, como fizeram para Java 6->7 e Java 7->8. Se ainda não o fez, a sugestão é migrar para o 10 e embarcar no novo trem de lançamentos. Finalmente, a Oracle postou mais informações sobre o roteiro para o Java Client (incluindo Applets e Web Start).

No front do OpenJDK, a Oracle planeja continuar liderando e contribuindo para o projeto JDK 8 Updates até janeiro de 2019, antes do qual será feita uma chamada para novos mantenedores (como tem sido prática por mais de uma década, consulte a pergunta anterior para mais detalhes).


❓ Pergunta 9: Sou um Cliente Oracle, como sou afetado?

Você está coberto pelo seu uso do Java SE dentro de um produto Oracle que tenha uma dependência do Java SE. Encontre mais detalhes via esta nota do My Oracle Support.


Nota de rodapé:

[1] – ;tldr para o plano que a Oracle anunciou para seus binários e builds – (a) mover todos os bits anteriormente de código fechado do Oracle JDK para o OpenJDK (b) publicar binários do OpenJDK sob a licença GPLv2+CPE e (c) garantir uma transição suave de modo que os binários do Oracle JDK e do OpenJDK sejam intercambiáveis.

💡 Um Resumo Rápido Sobre a Nova Assinatura Java SE

💡 Um Resumo Rápido Sobre a Nova Assinatura Java SE

Recentemente, foram anunciadas mudanças significativas no modelo de suporte e distribuição do Java SE. Este artigo apresenta um resumo dessas mudanças para ajudar desenvolvedores e empresas a entenderem o novo cenário.


🔍 Entendendo as Mudanças no Modelo de Suporte

O modelo de suporte do Java SE passou por uma evolução. Tradicionalmente, as atualizações públicas eram fornecidas gratuitamente para versões específicas. No novo modelo, para continuar recebendo atualizações de segurança e correções de bugs após um determinado período, é necessário uma assinatura.

Isso garante que as organizações que exigem suporte de longo prazo para ambientes de produção estáveis possam obtê-lo de maneira estruturada.


📦 O Que a Nova Assinatura Java SE Inclui?

A assinatura oferece benefícios essenciais para ambientes corporativos:

  • Atualizações de Segurança e Desempenho: Acesso contínuo a patches críticos.
  • Suporte Técnico: Assistência para resolver problemas em ambientes cobertos pela assinatura.
  • Licenças para Uso em Produção: Direito de executar as implementações relevantes do Java SE em ambientes produtivos.
  • Conformidade com Licenciamento: Ajuda a manter a conformidade com os termos de licenciamento do software Oracle.

🎯 Para Quem é Destinada Essa Assinatura?

A assinatura é voltada principalmente para empresas que utilizam o Java SE em ambientes de missão crítica e produção, especialmente aquelas que:

  • Precisam de suporte de longo prazo além dos ciclos públicos gratuitos.
  • Exigem garantias legais e de segurança fornecidas por um contrato comercial.
  • Possuem sistemas que não podem ser atualizados para novas versões principais frequentemente.

🆓 Alternativas Gratuitas e de Código Aberto

É importante destacar que existem opções gratuitas robustas disponíveis no ecossistema Java:

  • OpenJDK: A implementação de referência de código aberto do Java SE.
  • Binários de Outros Fornecedores: Diversos fornecedores oferecem builds gratuitos do OpenJDK com suporte opcional pago.

Essas alternativas são excelentes para desenvolvimento, teste e para muitas cargas de trabalho em produção.


🤔 Como Decidir o Que é Melhor para Você?

A escolha depende das necessidades específicas da sua organização. Recomenda-se considerar as seguintes perguntas:

  • Seu ambiente de produção requer suporte comercial com garantias contratuais?
  • Você precisa de atualizações de segurança para versões específicas do JDK por muitos anos?
  • A sua equipe precisa de acesso a suporte técnico direto do fornecedor?

Se a resposta for "sim" para essas questões, avaliar uma assinatura comercial é um passo prudente.


📚 Próximos Passos e Recursos

Para tomar uma decisão informada, consulte a documentação oficial e os detalhes dos termos de licenciamento. Recomenda-se também avaliar as necessidades de suporte de todos os times dentro da organização que utilizam Java.

O ecossistema Java continua vibrante, com múltiplas opções para atender a diferentes perfis de uso, desde desenvolvedores individuais até grandes corporações.

🚀 Java Mission Control – Agora também para binários do OpenJDK!

Java Mission Control – Agora também para binários do OpenJDK!

Existem planos para disponibilizar a tecnologia de código aberto JDK Mission Control (JMC) como um download separado para atender usuários tanto do OpenJDK quanto do Oracle JDK.


Aqui estão algumas das razões:

Para disponibilizar a todos os usuários Java

O Java Flight Recorder (JFR) agora é de código aberto. O JFR será incluído nos binários do OpenJDK e do Oracle JDK a partir do Java SE 11. Ter um único download separado do JMC para Oracle JDK e OpenJDK mantém a simplicidade.


Para permitir atualizações independentes do JMC

Como um download separado, o JMC pode ser atualizado independentemente dos lançamentos do Java SE. Isso permite oferecer novas capacidades de monitoramento e diagnóstico em várias versões do Java SE simultaneamente. Recursos podem ser adicionados ao JMC no meio de um ciclo de lançamento do Java SE.


Agora é possível empacotar eficientemente um JMC autônomo

Aproveitando os recursos de modularidade introduzidos com o JDK 9, é possível criar um runtime otimizado e personalizado para o JMC. Ele pode incluir tudo o que é necessário para essa versão do JMC, como componentes JavaFX, enquanto remove tudo o que não é exigido pelo JMC, tornando o tamanho do runtime do aplicativo consideravelmente menor.


Porque o JMC funciona com muitas versões do JDK e OpenJDK

Versões mais recentes do JMC podem interagir com versões mais antigas do JDK (do JDK 7u40 acima). É comum usar uma única versão do JMC para interagir com lançamentos atuais e antigos do JDK. Isso fica mais claro se o JMC for um download separado.


Para evitar duplicação e confusão

É um cenário comum um único desenvolvedor precisar de múltiplas instâncias do JDK no mesmo sistema. Ter cada um desses JDKs incluindo sua própria cópia duplicada do JMC, quando uma única versão pode lidar com todos, desperdiça espaço. Também pode levar a confusão, pois diferentes versões do JDK podem incluir diferentes versões do JMC, todas com (às vezes sutis) diferenças na funcionalidade.

🚀 Avanço Rápido para o Java 11

Avanço Rápido para o Java 11

Com o Java 11 prestes a ser lançado, é momento de analisar o efeito que o novo ritmo de lançamentos teve na adoção das novas versões.


Mudando o Ritmo das Mudanças

As novas versões do Java costumavam levar um bom tempo para serem adotadas pelos desenvolvedores. Por exemplo, o Java SE 5.0 introduziu mudanças importantes, como anotações e genéricos, em 2004. Levou dois anos, até 2006, para que uma versão da IDE Eclipse que fosse testada e validada no Java SE 5.0 fosse lançada. Somente então os desenvolvedores que usavam o Eclipse puderam começar a adotar o Java SE 5.0 de forma plena como sua plataforma principal.

Muito mudou no ecossistema Java na década desde 2004. O Java SE 8 foi lançado em 2014, introduzindo outra grande mudança na linguagem: as lambda expressions. No entanto, em poucos dias, novas versões das IDEs Eclipse, IntelliJ IDEA e NetBeans, testadas e validadas no JDK 8, já estavam disponíveis. Isso permitiu que os desenvolvedores começassem a adotar o Java SE 8 quase imediatamente após seu lançamento.

E muitos o fizeram, tornando o Java SE 8 a versão mais rapidamente adotada até então. O número de downloads do JDK 8 aumentou mais de 30% em comparação com o JDK 7 no mesmo período inicial de lançamento.


Em Frente para o 9

Com o novo ritmo semestral de lançamentos do Java SE a partir do Java SE 9, vimos o mesmo padrão de suporte rápido às novas versões da plataforma pelas principais IDEs. Engenheiros continuam a trabalhar em conjunto com desenvolvedores de mais de 100 bibliotecas e ferramentas Java de código aberto populares em todo o ecossistema para remover possíveis barreiras à adoção de novas versões.

Consequentemente, muitas bibliotecas e ferramentas populares estavam prontas para o Java 9 no momento de seu lançamento, ou logo em seguida. Isso incluiu ferramentas como Apache Ant, Apache Maven, Gradle, bibliotecas como ByteBuddy, JUnit, JaCoCo, Apache Lucene e frameworks como Akka, Spring Framework e WildFly.

Como resultado, o número de downloads do JDK 9 no lançamento do Java SE 9 foi mais de 10% maior do que o do lançamento do JDK 8.


Avanço Rápido para o 10

Vimos um padrão semelhante entre os desenvolvedores com o JDK 10. O Java SE 10 registrou 20% mais downloads de JDK do que o JDK 8 no mesmo período durante o lançamento do Java SE 8. Assim como com o JDK 9, IDEs, ferramentas, bibliotecas e frameworks populares rapidamente anunciaram seu suporte para a nova versão do Java.

Isso mostra como um aspecto importante do novo ritmo de lançamentos está funcionando incrivelmente bem — ele realmente está colocando novos recursos do Java, como a inferência de tipo de variável local no Java SE 10, nas mãos de mais desenvolvedores muito mais rápido do que antes.


Em Direção ao 11

No passado, cada nova versão da plataforma Java levava vários anos para ser desenvolvida e, no processo, acumulava milhares de melhorias grandes e pequenas, mudanças e correções de bugs. Levava muito tempo para ser construída e depois levava muito tempo para se familiarizar com ela, devido ao escopo muito amplo de cada versão.

Sob o novo ritmo de lançamentos, cada versão de recurso do Java é entregue em uma fração do tempo que levava no passado e, consequentemente, cada versão tem um escopo muito menor. Como consequência, o tempo necessário para se familiarizar com ela é muito mais curto, pois há muito menos mudanças para assimilar. Na prática, isso significa que muitas das ferramentas, bibliotecas e frameworks populares que estavam prontos para o Java SE 9 e Java SE 10 já conseguiram se preparar para o Java SE 11.

Em outras palavras, desde o Spring Boot e Spring Framework, passando por Mockito e ByteBuddy, até Apache Cassandra, IntelliJ IDEA, Jenkins, Eclipse IDE e Atlassian, grandes partes do ecossistema Java anunciaram que estão prontas para o Java SE 11 ou que já estão trabalhando para suportá-lo.

Dado que esse é o caso, não deve ser surpresa que uma pesquisa recente tenha constatado que mais da metade dos entrevistados está considerando usar o Java SE 11 para implantação em um futuro próximo.

Para usuários que precisam adotar novas versões de forma mais conservadora, foi introduzida recentemente a Java SE Subscription: uma assinatura mensal simples e de baixo custo que inclui licenciamento e suporte do Java SE para uso em desktops, servidores ou implantações na nuvem. A assinatura fornece acesso a atualizações de desempenho, estabilidade e segurança testadas e certificadas para o Java SE, diretamente da fonte. Ela também inclui acesso ao suporte 24×7, suporte em 27 idiomas, recursos de gerenciamento, monitoramento e implantação de desktop do Java SE 8, entre outros benefícios.

O produto Java SE 11 é uma versão de suporte de longo prazo (LTS). A Java SE Subscription permite que esses usuários recebam atualizações nas versões LTS e permaneçam em uma determinada versão de lançamento LTS por pelo menos oito anos. As organizações podem facilmente adicionar às suas assinaturas a qualquer momento, conforme movem cargas de trabalho do desenvolvimento para a produção.

Usuários que não precisam adotar novas versões da plataforma de forma conservadora, por outro lado, podem continuar a aproveitar os benefícios de um rápido ritmo de lançamentos do Java, como foi o caso do JDK 9 e JDK 10, usando os builds do OpenJDK de código aberto e totalmente testados, conforme a plataforma Java continua a avançar mais rápido com a comunidade OpenJDK.

🔍 Lançamentos do Oracle JDK para Java 11 e Versões Posteriores

🔄 Resumo Executivo

A partir do Java 11, a Oracle fornecerá lançamentos do JDK sob a licença de código aberto GNU General Public License v2, com a Exceção de Classpath (GPLv2+CPE), e sob uma licença comercial para aqueles que usam o Oracle JDK como parte de um produto ou serviço Oracle, ou que não desejam usar software de código aberto. Essa combinação de uso de uma licença de código aberto e uma licença comercial substitui a licença histórica "BCL", que tinha uma combinação de termos comerciais gratuitos e pagos.

Serão fornecidas compilações diferentes para cada licença, mas essas compilações são funcionalmente idênticas, exceto por algumas diferenças cosméticas e de empacotamento, descritas em detalhes abaixo.


📜 Da BCL para a GPL

A Binary Code License para tecnologias Oracle Java SE ("BCL") tem sido a licença principal para tecnologias Oracle Java SE por mais de uma década. A BCL permite o uso sem taxas de licença sob certas condições. Para simplificar as coisas no futuro, a Oracle começou a fornecer compilações do OpenJDK com licença de código aberto a partir do Java 9, usando o mesmo modelo de licença da plataforma Linux. Se você está acostumado a obter binários Oracle Java SE gratuitamente, pode simplesmente continuar fazendo isso com as compilações OpenJDK da Oracle disponíveis em jdk.java.net. Se você está acostumado a obter binários Oracle Java SE como parte de um produto ou serviço comercial da Oracle, pode continuar a obter lançamentos do Oracle JDK por meio do My Oracle Support (MOS) e outros locais.


⚙️ Funcionalmente idênticos e intercambiáveis...

Historicamente, o JDK licenciado pela BCL da Oracle continha "recursos comerciais" que não estavam disponíveis nas compilações do OpenJDK. Conforme prometido, no entanto, no ano passado a Oracle contribuiu com esses recursos para a Comunidade OpenJDK, incluindo:

  • Java Flight Recorder
  • Java Mission Control
  • ZGC
  • AppCDS

A partir do Java 11 em diante, portanto, as compilações do Oracle JDK e do OpenJDK serão essencialmente idênticas.


🎨 ...ainda com algumas diferenças cosméticas e de empacotamento

Ainda restam um pequeno número de diferenças, algumas intencionais e cosméticas, e outras simplesmente porque é necessário mais tempo para discussão com os contribuidores do OpenJDK.

🚫 Opção -XX:+UnlockCommercialFeatures

O Oracle JDK 11 emite um aviso ao usar a opção

-XX:+UnlockCommercialFeatures
, enquanto nas compilações do OpenJDK esta opção resulta em um erro. Esta opção nunca fez parte do OpenJDK e não faria sentido adicioná-la agora, já que não há recursos comerciais no OpenJDK. Essa diferença permanece para facilitar a migração dos usuários do Oracle JDK 10 e versões anteriores para o Oracle JDK 11 e posteriores.


📊 Console de Gerenciamento Avançado

O Oracle JDK 11 pode ser configurado para fornecer dados de log de uso para a ferramenta "Advanced Management Console", que é um produto comercial separado da Oracle. Trabalhar-se-á com outros contribuidores do OpenJDK para discutir como esses dados de uso podem ser úteis no OpenJDK em versões futuras, se é que serão. Essa diferença permanece principalmente para fornecer uma experiência consistente aos clientes da Oracle até que tais decisões sejam tomadas.


🎯 Comportamento do javac –release

O comando

javac –release
se comporta de maneira diferente para os destinos Java 9 e Java 10, pois nessas versões o Oracle JDK continha alguns módulos adicionais que não faziam parte dos lançamentos correspondentes do OpenJDK:

javafx.base
javafx.controls
javafx.fxml
javafx.graphics
javafx.media
javafx.web
java.jnlp
jdk.jfr
jdk.management.cmm
jdk.management.jfr
jdk.management.resource
jdk.packager.services
jdk.snmp

Essa diferença permanece para fornecer uma experiência consistente para tipos específicos de uso legado. Esses módulos agora estão disponíveis separadamente como parte do OpenJFX, agora estão tanto no OpenJDK quanto no Oracle JDK porque eram recursos comerciais que a Oracle contribuiu para o OpenJDK (por exemplo, Flight Recorder) ou foram removidos do Oracle JDK 11 (por exemplo, JNLP).


ℹ️ Saída dos comandos java –version e java -fullversion

A saída dos comandos

java –version
e
java -fullversion
distinguirá as compilações do Oracle JDK das compilações do OpenJDK, para que as equipes de suporte possam diagnosticar quaisquer problemas que possam existir. Especificamente, executar
java –version
com uma compilação do Oracle JDK 11 resulta em:

java 11 2018-09-25
Java(TM) SE Runtime Environment 18.9 (build 11+28)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11+28, mixed mode)

E para uma compilação do OpenJDK 11:

openjdk version "11" 2018-09-25
OpenJDK Runtime Environment 18.9 (build 11+28)
OpenJDK 64-Bit Server VM 18.9 (build 11+28, mixed mode)

🔐 Provedores criptográficos de terceiros

O Oracle JDK sempre exigiu que os provedores criptográficos de terceiros fossem assinados por um certificado conhecido. A estrutura de criptografia no OpenJDK tem uma interface criptográfica aberta, o que significa que não restringe quais provedores podem ser usados. O Oracle JDK 11 continuará a exigir uma assinatura válida, e as compilações do Oracle OpenJDK continuarão a permitir o uso de um provedor de criptografia de terceiros com assinatura válida ou não assinado.


📦 Instaladores, marcação e empacotamento JRE

O Oracle JDK 11 continuará a incluir instaladores, marcação e empacotamento JRE para uma experiência consistente com usos legados de desktop. As compilações do Oracle OpenJDK estão atualmente disponíveis como arquivos zip e tar.gz, enquanto formatos de distribuição alternativos estão sendo considerados.


🏷️ Como devemos chamá-los?

Idealmente, simplesmente nos referiríamos a todas as compilações do Oracle JDK como "Oracle JDK", seja sob a GPL ou a licença comercial, dependendo da sua situação. No entanto, por razões históricas, enquanto as pequenas diferenças remanescentes existirem, nos referiremos a elas separadamente como compilações OpenJDK da Oracle e Oracle JDK.

🚀 Construindo o JDK 11 Juntos: Uma Celebração das Contribuições da Comunidade

🚀 Construindo o JDK 11 Juntos

Com o lançamento recente do Java 11, é hora de olhar para trás, para o desenvolvimento da segunda versão de recursos no novo ritmo de lançamentos semestrais. Vamos celebrar as muitas contribuições da Comunidade OpenJDK vindas de vários indivíduos e organizações — todos nós construímos o JDK 11, juntos!


📊 Proporção de Correções no JDK 11

A taxa geral de mudança no JDK ao longo do tempo permaneceu essencialmente constante por muitos anos, mas, sob o novo ritmo, a taxa na qual as mudanças são disponibilizadas aumentou drasticamente. Em vez de dezenas de milhares de correções e cerca de uma centena de JEPs serem disponibilizados em um lançamento enorme a cada poucos anos, as mudanças são disponibilizadas em lançamentos menores em uma programação mais gerenciável e previsível. Essas mudanças podem variar de grandes recursos a pequenas melhorias, manutenção de rotina, correções de bugs e melhorias na documentação. Cada uma dessas mudanças é representada em um único commit para um único problema no JDK Bug System.

Dos 2.468 problemas do JIRA marcados como corrigidos no JDK 11, 1.963 foram concluídos por pessoas que trabalham na Oracle, enquanto 505 foram contribuídos por desenvolvedores individuais e desenvolvedores que trabalham para outras organizações. Ao percorrer os problemas e compilar os dados organizacionais dos responsáveis, obtém-se o seguinte gráfico das organizações que patrocinam o desenvolvimento de correções no JDK 11:

Embora os desenvolvedores empregados pela Oracle tenham resolvido 80% dos problemas do JIRA durante o desenvolvimento do JDK 11, 20% foram corrigidos por desenvolvedores que trabalham para outras organizações. Os desenvolvedores que trabalham para as cinco próximas maiores organizações contribuintes, SAP (7%), Red Hat (5%), Google (3%), BellSoft (1%) e IBM (1%), corrigiram coletivamente 17% desses problemas. Desenvolvedores independentes contribuíram com 2% das correções no JDK 11.

Por último, mas não menos importante, o um por cento restante das correções foi contribuído coletivamente por desenvolvedores de uma ampla gama de organizações, incluindo Alibaba, Amazon, ARM, Azul, Intel, JetBrains, Linaro e Qualcomm Datacenter Technologies.


⏳ Mas espere, tem mais

Muito mais trabalho vai para um lançamento do JDK, além dos commits individuais. Existem JEPs, revisões de código, relatórios de bugs e discussões em listas de e-mail, tanto no Projeto JDK quanto nos vários Projetos OpenJDK onde se originaram recursos e correções destinados ao JDK 11. Estes incluem o Projeto Valhalla e o Projeto Amber, ambos liderados por Brian Goetz da Oracle, a Porta AArch64, liderada por Andrew Haley da Red Hat, e o Projeto ZGC, liderado por Per Lidén da Oracle.

Com o JDK 11 lançado, o trabalho na primeira atualização do JDK 11 liderada pela Oracle no repositório do Projeto JDK Updates também começou.


🙏 Obrigado pelo JDK 11, pessoal!

Finalmente, é hora de agradecer a todos os desenvolvedores que contribuíram com código para o JDK 11 e às suas organizações patrocinadoras. Um agradecimento especial também aos muitos desenvolvedores experientes que revisaram as mudanças propostas, aos primeiros usuários que testaram as versões de acesso antecipado e relataram problemas, e aos profissionais pacientes que forneceram feedback nas listas de e-mail do OpenJDK.

🆕🔢 Um Novo Esquema de String de Versão para o JDK 9

🆕🔢 Um Novo Esquema de String de Versão para o JDK 9

Uma mudança significativa foi proposta para o JDK 9: um novo formato de string de versão. Este novo esquema foi projetado para ser facilmente compreensível por humanos e máquinas, atender aos requisitos atuais e futuros de versionamento e seguir as práticas recomendadas da indústria de software.


🎯 Por que Mudar?

O formato de versão atual do JDK (JDK 8 e anteriores) tem várias limitações que se tornaram aparentes ao longo dos anos. A versão $MAJOR.$MINOR.$SECURITY não é flexível o suficiente para os novos ciclos de lançamento mais rápidos. Além disso, a string de versão 1.8.0_92 é semanticamente incorreta, pois o 1.8 não é mais um 'major version' no sentido convencional.

O novo esquema visa resolver essas questões, oferecendo uma estrutura clara para os próximos anos.


📦 O Novo Formato

O novo formato de string de versão segue a seguinte estrutura geral:

$MAJOR.$MINOR.$SECURITY.$PATCH

Onde:

  • $MAJOR: A versão principal. Será incrementado quando mudanças significativas e incompatíveis forem feitas (por exemplo, JDK 9, JDK 10).
  • $MINOR: A versão menor. Será incrementado para lançamentos de funcionalidades que não quebram compatibilidade.
  • $SECURITY: A versão de segurança. Será incrementado para atualizações de segurança críticas.
  • $PATCH: A versão de patch. Será incrementado para correções de bugs não relacionados à segurança.

🔧 Exemplos Práticos

Suponha que a primeira versão do JDK 9 seja lançada. Suas strings de versão poderiam evoluir da seguinte forma:

9.0.1.0  // Versão inicial
9.0.1.1  // Corrigido um bug de inicialização (patch)
9.0.2.0  // Aplicado um patch de segurança crítico
9.1.0.0  // Adicionado um novo recurso compatível (minor release)

Para o JDK 10, a sequência recomeçaria:

10.0.0.0 // Versão principal inicial

⚙️ Impacto para Desenvolvedores

A API java.lang.Runtime.Version foi estendida para analisar e representar este novo formato. Desenvolvedores que analisam programaticamente a string de versão devem migrar para esta API.

Exemplo de uso:

Runtime.Version ver = Runtime.version();
System.out.println("Major: " + ver.major());
System.out.println("Minor: " + ver.minor());
System.out.println("Security: " + ver.security());
System.out.println("Patch: " + ver.patch());

Essa mudança também afeta propriedades do sistema como java.version, java.runtime.version e java.vm.version, que agora refletirão o novo esquema.


✅ Conclusão

A adoção deste novo esquema de versionamento é um passo importante para modernizar o ciclo de vida de lançamento do JDK. Ele proporciona a clareza e a flexibilidade necessárias para os futuros lançamentos mais ágeis e previsíveis, beneficiando tanto os mantenedores quanto os usuários finais da plataforma Java.

Esta mudança estabelece uma base sólida para o versionamento do JDK nos próximos anos, alinhando-o com as melhores práticas da indústria.

⚖️ Compreendendo o OpenJDK Community TCK License Agreement (OCTLA)

⚖️ O OpenJDK Community TCK License Agreement (OCTLA)

Depois de lançar a Comunidade OpenJDK como o lugar para colaborar em implementações de código aberto da Plataforma Java SE em 2006, o próximo passo lógico foi disponibilizar o Java SE TCK (JCK) para aqueles que trabalham e contribuem para o OpenJDK. A Sun Microsystems fez isso através do "OpenJDK Community TCK License Agreement" (OCTLA), disponibilizado em 2007 com versões certificadas aparecendo em 2008. A Oracle deu continuidade e expandiu esse programa, lançando um OCTLA para o Java SE 7, outro para o Java SE 8 e, considerando o novo ritmo de lançamentos, um único acordo para o Java SE 9 e versões posteriores. Houve dezenas de signatários nessas versões do Java SE.


O FAQ inicial do OCTLA ainda está disponível aqui. A Oracle continuou a aplicar as tradições e a intenção do programa OCTLA como ele foi originalmente concebido. Ou seja, o OCTLA é para indivíduos e organizações que trabalham e contribuem para a Comunidade OpenJDK, com implementações testadas pelo OCTLA de tais indivíduos e organizações distribuídas apenas sob a licença GPL do código do OpenJDK. Como observado no FAQ, o OCTLA não é para "implementações independentes de padrões de tecnologia Java". Para implementações independentes, a Oracle oferece opções comerciais de JCK, o que ajuda a financiar o desenvolvimento geral do Java. De fato, muitos dos signatários do OCTLA que participam da Comunidade OpenJDK também têm acordos comerciais de JCK para seus produtos e serviços baseados em implementação independente (não-OpenJDK). Alguns exemplos de implementações independentes de padrões de tecnologia Java ao longo do tempo incluem o BEA JRockit e o IBM J9.


A Oracle aplicou consistentemente o espírito e a intenção deste programa de longa data para o benefício da Comunidade OpenJDK, e planeja continuar o programa como vem fazendo desde a aquisição da Sun.

🚀 Agora Disponível: Guia de Migração do Oracle JRockit JVM para o HotSpot JVM

Agora Disponível: Guia de Migração do Oracle JRockit JVM para o HotSpot JVM


A Visão da Fusão

Durante a conferência JavaOne de 2010, foi anunciado que as JVMs Oracle JRockit e HotSpot seriam fundidas, incorporando ao HotSpot as funcionalidades que eram exclusivas do JRockit.

Com o JDK 7, esse trabalho começou a ser entregue, sendo concluído com o JDK 8. Enquanto isso, os clientes que usavam o Oracle JRockit JVM continuaram a receber atualizações de segurança periódicas e correções de bugs.


Suporte Contínuo e Migração

As versões de CPU (atualizações críticas de patch) e correções de bugs para o Java SE 6 JRockit (apenas R28) continuarão a ser fornecidas até o final da fase de suporte estendido, atualmente programada para dezembro de 2018.

Foi publicado um Guia de Migração para clientes que estão migrando do Oracle JRockit JVM para o HotSpot JVM. Ele fornece informações sobre muitas ferramentas e opções comuns disponíveis para o JRockit e suas equivalentes no HotSpot.


Próximos Passos para Desenvolvedores

Para os desenvolvedores que ainda utilizam o JRockit em ambientes de produção, este guia é um recurso essencial para planejar a transição para o HotSpot, garantindo continuidade e aproveitando o roadmap unificado do Java na Oracle.

🔒 Plano da Oracle para Remover a Confiança em Certificados TLS da Symantec no JDK

📅 Atualização 2019-01-25: Prazo Estendido para Certificados Gerenciados pela Apple

A confiança em certificados emitidos por duas subautoridades de certificação gerenciadas pela Apple será mantida por um período mais longo. As instruções sobre como reativar a confiança nas autoridades de certificação raiz afetadas foram atualizadas.


🔍 Introdução

O JDK da Oracle deixará de confiar em certificados TLS emitidos pela Symantec, alinhando-se a planos semelhantes anunciados recentemente por Google, Mozilla, Apple e Microsoft. A lista de certificados afetados inclui certificados das marcas GeoTrust, Thawte e VeriSign, que eram gerenciados pela Symantec.


⏰ Linha do Tempo da Mudança

A partir das versões de patch crítico planejadas para 16 de abril de 2019, todas as versões suportadas do JDK (12, 11, 8 e 7) começarão a remover a confiança em novos certificados de servidor TLS emitidos pelas autoridades de certificação afetadas.

📜 Certificados Existentes vs. Novos

  • Certificados emitidos antes de 16 de abril de 2019: Continuarão sendo confiáveis até sua data de expiração.
  • Certificados emitidos após 16 de abril de 2019: Serão rejeitados.

Informações sobre como substituir certificados Symantec por um certificado DigiCert estão disponíveis na página de suporte da DigiCert.


⚙️ Impacto Técnico e Como Funciona

As novas restrições serão aplicadas na implementação do JDK (o Provedor SunJSSE) da API Java Secure Socket Extension (JSSE). Uma sessão TLS não será negociada se a cadeia de certificados do servidor estiver ancorada por qualquer uma das Autoridades de Certificação listadas na tabela abaixo.

💻 Exemplo de Erro

Uma aplicação receberá uma exceção com uma mensagem indicando que a âncora de confiança não é confiável, por exemplo:

TLS Server certificate issued after 2019-04-16 and anchored by a distrusted legacy Symantec root CA: CN=GeoTrust Global CA, O=GeoTrust Inc., C=US

🛠️ Contornando as Restrições (Medida Temporária)

Se necessário, é possível contornar as restrições comentando ou removendo "SYMANTEC_TLS" da propriedade de segurança jdk.security.caDistrustPolicies no arquivo de configuração java.security.

# Exemplo: Para desativar a política de desconfiança SYMANTEC_TLS
# jdk.security.caDistrustPolicies=SYMANTEC_TLS

Atenção: Esta é uma solução temporária. A ação correta é substituir o certificado.


📋 Autoridades de Certificação Raiz da Symantec Afetadas no JDK

A restrição será imposta aos seguintes certificados raiz da Symantec incluídos no JDK:

Nome Distinto (Distinguished Name)Imprensa Digital (Fingerprint) SHA-256
CN=GeoTrust Global CA, O=GeoTrust Inc., C=USFF:85:6A:2D:25:1D:CD:88:D3:66:56:F4:50:12:67:98:CF:AB:AA:DE:40:79:9C:72:2D:E4:D2:B5:DB:36:A7:3A
CN=GeoTrust Primary Certification Authority, O=GeoTrust Inc., C=US37:D5:10:06:C5:12:EA:AB:62:64:21:F1:EC:8C:92:01:3F:C5:F8:2A:E9:8E:E5:33:EB:46:19:B8:DE:B4:D0:6C
CN=GeoTrust Primary Certification Authority – G2, OU=(c) 2007 GeoTrust Inc. – For authorized use only, O=GeoTrust Inc., C=US5E:DB:7A:C4:3B:82:A0:6A:87:61:E8:D7:BE:49:79:EB:F2:61:1F:7D:D7:9B:F9:1C:1C:6B:56:6A:21:9E:D7:66
CN=GeoTrust Primary Certification Authority – G3, OU=(c) 2008 GeoTrust Inc. – For authorized use only, O=GeoTrust Inc., C=USB4:78:B8:12:25:0D:F8:78:63:5C:2A:A7:EC:7D:15:5E:AA:62:5E:E8:29:16:E2:CD:29:43:61:88:6C:D1:FB:D4
CN=GeoTrust Universal CA, O=GeoTrust Inc., C=USA0:45:9B:9F:63:B2:25:59:F5:FA:5D:4C:6D:B3:F9:F7:2F:F1:93:42:03:35:78:F0:73:BF:1D:1B:46:CB:B9:12
CN=thawte Primary Root CA, OU=”(c) 2006 thawte, Inc. – For authorized use only”, OU=Certification Services Division, O=”thawte, Inc.”, C=US8D:72:2F:81:A9:C1:13:C0:79:1D:F1:36:A2:96:6D:B2:6C:95:0A:97:1D:B4:6B:41:99:F4:EA:54:B7:8B:FB:9F
CN=thawte Primary Root CA – G2, OU=”(c) 2007 thawte, Inc. – For authorized use only”, O=”thawte, Inc.”, C=USA4:31:0D:50:AF:18:A6:44:71:90:37:2A:86:AF:AF:8B:95:1F:FB:43:1D:83:7F:1E:56:88:B4:59:71:ED:15:57
CN=thawte Primary Root CA – G3, OU=”(c) 2008 thawte, Inc. – For authorized use only”, OU=Certification Services Division, O=”thawte, Inc.”, C=US4B:03:F4:58:07:AD:70:F2:1B:FC:2C:AE:71:C9:FD:E4:60:4C:06:4C:F5:FF:B6:86:BA:E5:DB:AA:D7:FD:D3:4C
EMAILADDRESS=premium-server@thawte.com, CN=Thawte Premium Server CA, OU=Certification Services Division, O=Thawte Consulting cc, L=Cape Town, ST=Western Cape, C=ZA3F:9F:27:D5:83:20:4B:9E:09:C8:A3:D2:06:6C:4B:57:D3:A2:47:9C:36:93:65:08:80:50:56:98:10:5D:BC:E9
OU=VeriSign Trust Network, OU=”(c) 1998 VeriSign, Inc. – For authorized use only”, OU=Class 2 Public Primary Certification Authority – G2, O=”VeriSign, Inc.”, C=US3A:43:E2:20:FE:7F:3E:A9:65:3D:1E:21:74:2E:AC:2B:75:C2:0F:D8:98:03:05:BC:50:2C:AF:8C:2D:9B:41:A1
OU=Class 3 Public Primary Certification Authority, O=”VeriSign, Inc.”, C=USA4:B6:B3:99:6F:C2:F3:06:B3:FD:86:81:BD:63:41:3D:8C:50:09:CC:4F:A3:29:C2:CC:F0:E2:FA:1B:14:03:05
OU=VeriSign Trust Network, OU=”(c) 1998 VeriSign, Inc. – For authorized use only”, OU=Class 3 Public Primary Certification Authority – G2, O=”VeriSign, Inc.”, C=US83:CE:3C:12:29:68:8A:59:3D:48:5F:81:97:3C:0F:91:95:43:1E:DA:37:CC:5E:36:43:0E:79:C7:A8:88:63:8B
CN=VeriSign Class 3 Public Primary Certification Authority – G3, OU=”(c) 1999 VeriSign, Inc. – For authorized use only”, OU=VeriSign Trust Network, O=”VeriSign, Inc.”, C=USEB:04:CF:5E:B1:F3:9A:FA:76:2F:2B:B1:20:F2:96:CB:A5:20:C1:B9:7D:B1:58:95:65:B8:1C:B9:A1:7B:72:44
CN=VeriSign Class 3 Public Primary Certification Authority – G4, OU=”(c) 2007 VeriSign, Inc. – For authorized use only”, OU=VeriSign Trust Network, O=”VeriSign, Inc.”, C=US69:DD:D7:EA:90:BB:57:C9:3E:13:5D:C8:5E:A6:FC:D5:48:0B:60:32:39:BD:C4:54:FC:75:8B:2A:26:CF:7F:79
CN=VeriSign Class 3 Public Primary Certification Authority – G5, OU=”(c) 2006 VeriSign, Inc. – For authorized use only”, OU=VeriSign Trust Network, O=”VeriSign, Inc.”, C=US9A:CF:AB:7E:43:C8:D8:80:D0:6B:26:2A:94:DE:EE:E4:B4:65:99:89:C3:D0:CA:F1:9B:AF:64:05:E4:1A:B7:DF
CN=VeriSign Universal Root Certification Authority, OU=”(c) 2008 VeriSign, Inc. – For authorized use only”, OU=VeriSign Trust Network, O=”VeriSign, Inc.”, C=US23:99:56:11:27:A5:71:25:DE:8C:EF:EA:61:0D:DF:2F:A0:78:B5:C8:06:7F:4E:82:82:90:BF:B8:60:E8:4B:3C

Se você possui um certificado de servidor TLS emitido por uma das ACs acima, deve ter recebido uma mensagem da DigiCert com informações sobre a substituição desse certificado, sem custo.


🍏 Exceção: Certificados Gerenciados pela Apple

Certificados emitidos por duas autoridades de certificação subordinadas gerenciadas pela Apple, identificadas abaixo, continuarão a ser confiáveis desde que emitidos em ou antes de 31 de dezembro de 2019.

Nome Distinto (Distinguished Name)Imprensa Digital (Fingerprint) SHA-256Data de Desconfiança
CN=Apple IST CA 2 – G1, OU=Certification Authority, O=Apple Inc., C=USAC:2B:92:2E:CF:D5:E0:17:11:77:2F:EA:8E:D3:72:DE:9D:1E:22:45:FC:E3:F5:7A:9C:DB:EC:77:29:6A:42:4B2019-12-31
CN=Apple IST CA 8 – G1, OU=Certification Authority, O=Apple Inc., C=USA4:FE:7C:7F:15:15:5F:3F:0A:EF:7A:AA:83:CF:6E:06:DE:B9:7C:A3:F9:09:DF:92:0A:C1:49:08:82:D4:88:ED2019-12-31

🔧 Como Verificar seus Certificados

É possível usar a utilitário keytool do JDK para imprimir detalhes da cadeia de certificados, da seguinte forma:

keytool -v -list -alias <seu_alias_de_servidor> -keystore <seu_arquivo_de_keystore>

Se algum dos certificados na cadeia for emitido por uma das autoridades de certificação raiz na tabela acima e aparecer na saída, será necessário atualizar o certificado ou entrar em contato com a organização que gerencia o servidor, se não for o seu.


✅ Próximos Passos e Ação Recomendada

  1. Verifique a origem dos certificados TLS usados em suas aplicações e servidores.
  2. Substitua quaisquer certificados de servidor TLS emitidos pelas autoridades de certificação listadas, preferencialmente por um fornecedor diferente (como DigiCert).
  3. Teste a nova configuração em um ambiente de homologação.
  4. Planeje a implantação antes da data limite de 16 de abril de 2019 para evitar interrupções.

Manter a segurança da infraestrutura de certificados é essencial para a confiança na internet e a proteção de dados.

📚 FAQ sobre Lançamentos do Oracle Java SE: Licenciamento, Atualizações e Suporte

📋 Perguntas Frequentes sobre Lançamentos do Oracle Java SE

P1: O Java ainda é gratuito após janeiro de 2019?

Com certeza. Conforme acontece há mais de duas décadas, a Oracle mantém o Java gratuito e aberto, fornecendo atualizações de estabilidade, desempenho e segurança para a versão atual, sem custo. A Oracle também continua a fornecer gratuitamente atualizações críticas de patch, agendadas com mais de um ano de antecedência, atualizações adicionais quando necessário e duas atualizações de recursos (que também incluem atualizações críticas de patch) por ano sob o novo ritmo de lançamento.

Todo esse desenvolvimento é feito no OpenJDK, comunidade de código aberto, disponibilizando as contribuições para que qualquer pessoa as porte, analise e use como código aberto. É possível baixar as atualizações mais recentes do Java da Oracle, gratuitamente, sob uma licença de código aberto em jdk.java.net, e para fins de desenvolvimento e teste como o Oracle JDK no OTN.


P2: O que significa "Fim das Atualizações Públicas"?

Após cinco anos de disponibilidade pública, o Java 8 passou pelo "Fim das Atualizações Públicas" no início de 2019 – assim como o Java 5 em 2009, o Java 6 em 2013 e o Java 7 em 2015. A Oracle fornece atualizações gratuitas, previsíveis e agendadas com antecedência, incluindo atualizações de estabilidade, desempenho e segurança das versões atuais em jdk.java.net e OTN. Versões legadas continuam disponíveis e com suporte para clientes Oracle via My Oracle Support, conforme os prazos publicados.


P3: O que significa "gratuito para uso pessoal"?

Transições anteriores de "Fim das Atualizações Públicas" (Java 5 em 2009, Java 6 em 2013 e Java 7 em 2015) ocorreram em uma data fixa, para todos os tipos de usuários, ao mesmo tempo.

Conforme anunciado no ano passado, a Oracle estendeu as atualizações públicas para o Java 8 de setembro de 2018 para janeiro de 2019. A Oracle também estendeu ainda mais as atualizações públicas gratuitas do Java 8 para uso pessoal, individual em desktop ou laptop até pelo menos o final de 2020 [Nota: esta data foi estendida indefinidamente; consulte este post para mais informações]. Isso fornece atualizações gratuitas para indivíduos que usam aplicativos do tipo "B2C" que ainda podem usar recursos legados do Java 8 como Applets, Java Web Start e JavaFX (que foram removidos no Java 9 ou versões posteriores). Mais informações sobre este tópico foram publicadas no ano passado. Isso significa que indivíduos que dependem do Java 8 para jogos, bancos pessoais ou outras atividades do tipo consumidor individual em seus computadores desktop ou laptop continuarão recebendo atualizações gratuitas pelo menos até 2020.

Usuários comerciais podem atualizar para uma versão mais recente do Java, disponível gratuitamente pela Oracle, ou considerar uma Java SE Subscription se for importante permanecer em versões mais antigas, como o Java 8.


P4: Quais são os prazos do "Fim das Atualizações Públicas" do Java 8?

A Atualização Crítica de Patch do Java 8 (8u201 e a 8u202 Patch Set Update relacionada) agendada para 15 de janeiro de 2019 foi a última atualização disponível sob a licença BCL, que é geralmente gratuita para uso geral em desktop e servidor, e tem sido a licença do Oracle JDK por vários anos. A seguinte atualização do Java 8, agendada para 16 de abril de 2019 (8u211 e a 8u212 Patch Set Update relacionada), foi disponibilizada sob uma nova licença que será gratuita para uso pessoal individual em desktop e gratuita para fins de desenvolvimento, teste, prototipagem e demonstração.

Os lançamentos mais recentes do Java permanecem gratuitos e sob uma licença de código aberto em jdk.java.net, ou gratuitos para licença de desenvolvimento, teste, prototipagem e demonstração no OTN. Java SE Subscriptions estão disponíveis para quem deseja continuar a usar as atualizações do Java 8 disponibilizadas a partir de 16 de abril de 2019 para fins comerciais ou de produção. O Java SE Subscription FAQ tem informações adicionais, incluindo preços.


P5: Uma atualização do Java 8, lançada antes de abril de 2019 e baixada sob a BCL, pode continuar sendo usada após janeiro de 2019?

Sim. Você pode continuar usando qualquer versão do Java sob os termos da licença sob a qual ela foi fornecida. O novo licenciamento para atualizações do Java 8 aplica-se apenas a atualizações lançadas sob a nova licença após janeiro de 2019, começando com a atualização trimestral agendada para 16 de abril de 2019.

Atualizações públicas mais antigas do Java, desde o Java 1.1, estão disponíveis nos Java Archives. Essas versões mais antigas são fornecidas para ajudar os desenvolvedores a depurar problemas em sistemas antigos. Elas não são atualizadas com os patches de segurança mais recentes e não são recomendadas para uso em produção.


P6: Sou um Cliente Oracle com um produto Oracle que usa Java. Você pode confirmar que as atualizações e o suporte do Java estão incluídos para uso com esse produto Oracle?

Sim. Se você é um Cliente Oracle com um produto Oracle suportado que requer Java SE, você continua a ter acesso às atualizações do Oracle Java, conforme exigido pelo seu produto Oracle, para o uso de produtos Oracle suportados, sem custo adicional. Consulte esta nota do My Oracle Support (MOS) para obter mais informações (requer login).


P7: Por que o Java Auto Update recomenda remover versões não utilizadas do Java?

O mecanismo de atualização do Java rotineiramente recomenda a remoção de versões mais antigas após concluir uma atualização, para manter seu sistema limpo.

A partir de janeiro de 2019, o mecanismo de atualização automática também pode detectar se você não usou o Java em seu computador por seis meses ou mais e, nesse caso, pode oferecer a remoção em vez da atualização do Java. Clientes que instalaram o Java a partir do Oracle eDelivery ou My Oracle Support não devem ver essas mensagens. Se você desinstalar o Java acidentalmente e decidir mais tarde que precisava dele, sempre poderá reinstalá-lo visitando java.com/download ou através de seus canais de suporte e distribuição ao cliente Oracle.


P8: E se eu for um ISV (Fornecedor Independente de Software)?

As respostas às perguntas frequentes acima se aplicam a ISVs e àqueles que usam Java para uso interno. ISVs que precisam permitir que seus usuários escolham qual versão do Java usar para executar seu software podem seguir a abordagem de suportar tanto a versão mais recente do Java fornecida gratuitamente pela Oracle quanto as versões mais antigas do Oracle Java disponíveis por meio do Java SE Subscription. ISVs que incorporam o Java em seus aplicativos podem escolher os lançamentos gratuitos de código aberto em jdk.java.net ou entrar em contato com a Oracle para distribuir atualizações do Oracle JDK.


P9: Que outros recursos estão disponíveis?

Informações adicionais e as últimas atualizações estão disponíveis nos canais oficiais do Java.