O Java 26 chega com o casamento de padrões em pleno funcionamento, a concorrência caminhando para a finalização e APIs pragmáticas para otimização de inicialização e criptografia. Após o intenso trabalho de linguagem realizado no Java 25, o Java 26 concentra-se em aprimorar as versões prévias existentes e fornecer primitivas de biblioteca que estavam faltando.
Este post é um guia prático: seções curtas, código executável e cenários concretos onde você usará cada recurso em breve. Cada trecho de código é intencionalmente minimalista para que você possa copiar, adaptar e executar rapidamente.
Observação : O Java 26 não é uma versão LTS . Ele recebe atualizações por 6 meses (até setembro de 2026). Para suporte a longo prazo, use o Java 21 LTS ou o Java 25 LTS.
- [FINAL] — estável, pronto para produção
- [PRÉ-VISUALIZAÇÃO] — requer
--enable-preview- [INCUBADOR] — experimental, pode sofrer alterações significativas
Destaques do Java 26
- [PRÉVIA] Tipos primitivos em padrões em qualquer lugar (JEP 530 – quarta prévia, lançamento em breve)
- [PRÉVIA] Maturidade da concorrência estruturada (JEP 525 – sexta prévia, próxima da versão final)
- [PRÉVIA] Constantes preguiçosas para aumento de desempenho na inicialização (JEP 526 – segunda prévia)
- [PRÉVIA] APIs de criptografia PEM (JEP 524 – segunda prévia)
- [FINAL] Cache AOT com qualquer GC – incluindo ZGC (JEP 516)
- [FINAL] HTTP/3 para o Cliente HTTP (JEP 517)
- [FINAL] Ganhos de desempenho do GC G1 (JEP 522)
- [FINAL] Campos finais ganhando força (JEP 500 – avisos hoje, negativas depois)
- [INCUBATOR] API de computação vetorial (JEP 529 – décima primeira incubadora)
Correspondência de linguagem e padrões
JEP 530: Tipos primitivos em padrões, instanceof e switch [PRÉVIA]
O que é: A correspondência de padrões agora funciona uniformemente em todos os tipos primitivos. Você pode usar `std::string` instanceof int x, vincular valores restritos com segurança em `std::string` switche verificar conversões sem perda silenciosa.
Quando você usará: análise de JSON com coerção de tipo, verificações seguras de intervalo numérico, expressão de regras de negócios com guardas.
Antes (conversão manual, verificações de tipo repetitivas):
// BEFORE (Java 25)
public class PriceAnalyzer {
static String category(Object price) {
if (price instanceof Integer) {
int p = (Integer) price;
return p < 100 ? "BUDGET" : p < 500 ? "MID" : "PREMIUM";
}
if (price instanceof Double) {
double d = (Double) price;
// Silent truncation risk if cast to int
if (d > 1000.0) return "PREMIUM";
return "MID";
}
if (price instanceof Long) {
long l = (Long) price;
return l > 10_000 ? "PREMIUM" : "BUSINESS";
}
return "UNKNOWN";
}
}
Após (padrões primitivos com estreitamento seguro):
// src/main/java/com/loiane/pricing/Category.java
package com.loiane.pricing;
public class PriceAnalyzer {
static String category(Object price) {
return switch (price) {
case int p when p < 100 -> "BUDGET";
case int p when p < 500 -> "MID";
case int p -> "PREMIUM";
case long l when l > 10_000 -> "PREMIUM";
case long l -> "BUSINESS";
// Only bind d to int x if conversion is exact (no silent loss)
case double d when d instanceof int x ->
"EXACT_INT: " + category(x);
case double d when d > 1000.0 -> "PREMIUM";
case double d -> "MID";
default -> "UNKNOWN";
};
}
public static void main(String[] args) {
System.out.println(category(50)); // BUDGET
System.out.println(category(300)); // MID
System.out.println(category(800)); // PREMIUM
System.out.println(category(15_000L)); // PREMIUM
System.out.println(category(500.0)); // EXACT_INT
System.out.println(category(500.5)); // MID
}
}
O que está acontecendo aqui?
case int pvincula-se exatamente a valores inteiros;LongeDoubletêm seus próprios casos.d instanceof int xVerifica se o valor doubledpode ser convertido exatamente para int (sem perda de precisão); somente então o vincula.- Os guards (
when) permitem expressar lógica de intervalo em linha.
Executar (pré-visualização):
javac --enable-preview --release 26 -d out src/main/java/com/loiane/pricing/Category.java
java --enable-preview -cp out com.loiane.pricing.PriceAnalyzer
Concorrência em escala
JEP 525: Concorrência estruturada [PRÉVIA]
O que é: Concorrência baseada em tarefas com cancelamento automático e propagação de erros. Criam-se subtarefas relacionadas, unindo-as em uma unidade; se uma falhar, as demais são canceladas automaticamente.
Quando usar: manipuladores de requisições web, operações de E/S paralelas, fluxos de trabalho com limites claros de sucesso/falha.
Antes (cancelamento manual, vazamentos de threads em caso de falha, tratamento complexo de erros):
// BEFORE (Java 25, using ExecutorService)
public class OrderService {
static class OrderData {
String customer;
List<String> items;
String address;
}
static OrderData fetchOrder(ExecutorService executor) throws Exception {
Future<String> customerFuture = executor.submit(() -> {
Thread.sleep(100); // simulate I/O
return "Alice";
});
Future<List<String>> itemsFuture = executor.submit(() -> {
Thread.sleep(150);
return List.of("Laptop", "Mouse");
});
Future<String> addressFuture = executor.submit(() -> {
Thread.sleep(200);
return "123 Main St";
});
// Problem: if customerFuture.get() throws, itemsFuture and addressFuture
// keep running (thread leak). Manual cancellation needed everywhere.
String customer = customerFuture.get();
List<String> items = itemsFuture.get();
String address = addressFuture.get();
return new OrderData(customer, items, address);
}
}
Após (tratamento e cancelamento estruturados e automáticos de erros):
// src/main/java/com/loiane/orders/OrderService.java
package com.loiane.orders;
import java.util.concurrent.StructuredTaskScope;
import java.util.concurrent.StructuredTaskScope.Joiner;
import java.util.List;
public class OrderService {
static class OrderData {
String customer;
List<String> items;
String address;
OrderData(String customer, List<String> items, String address) {
this.customer = customer;
this.items = items;
this.address = address;
}
}
static OrderData fetchOrder() throws Exception {
try (var scope = StructuredTaskScope.open(Joiner.allSuccessfulOrThrow())) {
var customerTask = scope.fork(() -> {
Thread.sleep(100);
return "Alice";
});
var itemsTask = scope.fork(() -> {
Thread.sleep(150);
return List.of("Laptop", "Mouse");
});
var addressTask = scope.fork(() -> {
Thread.sleep(200);
return "123 Main St";
});
scope.join(); // Wait for all; if any fails, cancel others automatically
return new OrderData(
customerTask.get(),
itemsTask.get(),
addressTask.get()
);
}
// Scope closed: all subtasks guaranteed to have finished
}
public static void main(String[] args) throws Exception {
var order = fetchOrder();
System.out.println("Customer: " + order.customer);
System.out.println("Items: " + order.items);
System.out.println("Address: " + order.address);
}
}
O que está acontecendo aqui?
StructuredTaskScope.open(Joiner.allSuccessfulOrThrow())Cria um escopo onde todas as subtarefas devem ser concluídas com sucesso.fork()Inicia cada tarefa assíncrona (thread virtual, por padrão no Java 21+).join()Aguarda a conclusão de todas as subtarefas; se alguma falhar, as outras são canceladas imediatamente.tryO parâmetro -with-resources garante que o escopo seja encerrado e a limpeza seja realizada.
Executar (pré-visualização):
javac --enable-preview --release 26 -d out src/main/java/com/loiane/orders/OrderService.java
java --enable-preview -cp out com.loiane.orders.OrderService
Otimização de startups
JEP 526: Constantes preguiçosas [PRÉVIA]
O que é: Imutabilidade diferida. Cria uma LazyConstant<T>variável que é inicializada no primeiro acesso, com semântica de “no máximo uma vez”, mesmo sob chamadas concorrentes. A JVM a trata como uma constante verdadeira após a inicialização, permitindo otimizações.
Quando usar: Inicialização da aplicação — adie inicializações dispendiosas (loggers, repositórios, configurações) até que sejam necessárias.
Antes (inicialização imediata ou bloqueio com verificação dupla, ambos problemáticos):
// BEFORE
public class Application {
// Eager: logger created even if app never logs
private static final Logger LOGGER = Logger.getLogger("com.app");
// Or: double-checked locking (verbose, not constant-folded)
private static volatile Logger logger;
static Logger getLogger() {
if (logger == null) {
synchronized (Application.class) {
if (logger == null) {
logger = Logger.getLogger("com.app");
}
}
}
return logger;
}
}
Após (constante preguiçosa com desempenho de ansioso):
// src/main/java/com/loiane/app/Application.java
package com.loiane.app;
import java.lang.LazyConstant;
import java.util.logging.Logger;
public class Application {
// Initialize lazily on first call; JVM constant-folds after init
private static final LazyConstant<Logger> LOGGER =
LazyConstant.of(() -> Logger.getLogger("com.loiane.app"));
static void logInfo(String msg) {
LOGGER.get().info(msg);
}
public static void main(String[] args) {
logInfo("App started"); // First call: logger created
logInfo("Processing"); // Subsequent: instant (constant-folded)
}
}
Para listas, use List.ofLazy():
// src/main/java/com/loiane/app/Pool.java
package com.loiane.app;
import java.util.List;
public class Pool {
static class Worker {
String name;
Worker(String name) { this.name = name; }
}
// Pool of 10 workers, each created on first access
static final List<Worker> WORKERS = List.ofLazy(10,
index -> new Worker("worker-" + index));
public static void main(String[] args) {
System.out.println(WORKERS.get(0).name); // Lazy init
System.out.println(WORKERS.get(0).name); // Instant (cached)
}
}
O que está acontecendo aqui?
LazyConstant.of(supplier)Cria um invólucro; liga para o fornecedor na primeira vez.get(), e nunca mais.List.ofLazy(size, indexedSupplier)Cria uma lista de tamanho fixo com elementos preguiçosos.- A JVM otimiza os acessos após a inicialização estar completa.
Executar (pré-visualização):
javac --enable-preview --release 26 -d out src/main/java/com/loiane/app/*.java
java --enable-preview -cp out com.loiane.app.Application
Criptografia e segurança
JEP 524: Codificações PEM de objetos criptográficos [PRÉ-VISUALIZAÇÃO]
O que é: APIs padrão para codificação/decodificação PEM de chaves, certificados e CRLs. Codifica para PEM para armazenamento/transporte; decodifica de PEM de volta para objetos criptográficos Java. Opcionalmente, criptografa chaves privadas.
Quando você usará: Gerenciamento de chaves, carregamento de certificados, compartilhamento seguro de chaves entre sistemas.
Antes (Base64 manual, modelo padrão, sem padrão):
// BEFORE (Java 25)
import java.security.KeyPairGenerator;
import java.security.KeyPair;
import java.util.Base64;
import java.nio.file.*;
public class KeyMgmt {
static void exportKey(KeyPair kp) throws Exception {
byte[] privateKeyBytes = kp.getPrivate().getEncoded();
String base64 = Base64.getEncoder().encodeToString(privateKeyBytes);
StringBuilder pem = new StringBuilder();
pem.append("-----BEGIN PRIVATE KEY-----\n");
// Manually format to 64-char lines
for (int i = 0; i < base64.length(); i += 64) {
int end = Math.min(i + 64, base64.length());
pem.append(base64, i, end).append("\n");
}
pem.append("-----END PRIVATE KEY-----\n");
Files.writeString(Path.of("key.pem"), pem);
}
}
Após (codificador/decodificador PEM limpo com criptografia opcional):
// src/main/java/com/loiane/crypto/KeyMgmt.java
package com.loiane.crypto;
import java.security.*;
import java.security.spec.*;
import java.nio.file.*;
import java.security.PEMEncoder;
import java.security.PEMDecoder;
public class KeyMgmt {
// Generate a keypair
static KeyPair generateKeyPair() throws Exception {
var gen = KeyPairGenerator.getInstance("RSA");
gen.initialize(2048);
return gen.generateKeyPair();
}
// Export keypair to PEM (no encryption)
static void exportKeyPair(KeyPair kp, Path path) throws Exception {
String pem = PEMEncoder.of().encodeToString(kp);
Files.writeString(path, pem);
System.out.println("Exported: " + path.getFileName());
}
// Export private key with password encryption
static void exportEncrypted(KeyPair kp, char[] password, Path path)
throws Exception {
var encoder = PEMEncoder.of().withEncryption(password);
String pem = encoder.encodeToString(kp.getPrivate());
Files.writeString(path, pem);
System.out.println("Exported encrypted: " + path.getFileName());
}
// Import from PEM
static KeyPair importKeyPair(Path path, char[] password) throws Exception {
String pem = Files.readString(path);
var decoder = PEMDecoder.of().withDecryption(password);
// Decoder infers type from PEM header
return (KeyPair) decoder.decode(pem);
}
public static void main(String[] args) throws Exception {
var kp = generateKeyPair();
exportKeyPair(kp, Path.of("public-private.pem"));
exportEncrypted(kp, "secret123".toCharArray(), Path.of("private-encrypted.pem"));
// Re-import
var restored = importKeyPair(
Path.of("private-encrypted.pem"),
"secret123".toCharArray()
);
System.out.println("Restored private key: " + restored.getPrivate().getAlgorithm());
}
}
O que está acontecendo aqui?
PEMEncoder.of()Cria um codificador;.encodeToString()retorna o texto PEM diretamente.withEncryption(password)Permite a criptografia baseada em senha para chaves privadas.PEMDecoder.of().withDecryption(password)Detecta automaticamente o tipo de chave a partir do cabeçalho PEM; descriptografa se necessário.
Executar (pré-visualização):
javac --enable-preview --release 26 -d out src/main/java/com/loiane/crypto/KeyMgmt.java
java --enable-preview -cp out com.loiane.crypto.KeyMgmt
JEP 500: Prepare-se para tornar final o significado final [FINAL]
O que é: A reflexão profunda (por exemplo, Field.set()em campos finais) agora emite um aviso. Em uma futura versão do Java, ela lançará uma exceção por padrão. Isso abre caminho para a verdadeira imutabilidade e otimizações da JVM.
Quando usar: Analise os avisos em seus logs e bibliotecas. Use --enable-final-field-mutation=ALL-UNNAMEDem produção se necessário, mas planeje refatorar o código.
Código (detectar mutação do campo final):
// src/main/java/com/loiane/finals/FinalTest.java
package com.loiane.finals;
import java.lang.reflect.Field;
public class FinalTest {
static class Config {
final String env = "prod";
}
public static void main(String[] args) throws Exception {
Config cfg = new Config();
System.out.println("Before: " + cfg.env);
// Reflection: mutate the final field
Field f = Config.class.getDeclaredField("env");
f.setAccessible(true);
f.set(cfg, "dev"); // Warning issued in Java 26
System.out.println("After: " + cfg.env); // Prints "dev"
}
}
Corra e preste atenção ao aviso:
javac -d out src/main/java/com/loiane/finals/FinalTest.java
java -cp out com.loiane.finals.FinalTest
# Output:
# WARNING: Final field env in class com.loiane.finals.FinalTest$Config
# has been mutated by class com.loiane.finals.FinalTest.main ...
Se precisar suprimir o aviso (temporariamente):
java --illegal-final-field-mutation=allow -cp out com.loiane.finals.FinalTest
Mas planeje migrar as bibliotecas de serialização para sun.reflect.ReflectionFactoryoutra solução.
Desempenho e GC
[FINAL]
JEP 516: Cache de objetos antecipado com qualquer GC [FINAL]
O que é: O cache AOT agora funciona com ZGC, não apenas com G1/Serial/Parallel. Utiliza um formato agnóstico ao GC (índices lógicos), de modo que o mesmo cache funciona em diferentes GCs.
Quando usar: Inicializações a frio de contêineres. Treine com qualquer coletor de lixo; use em produção com Z, G1 ou qualquer outro.
Fluxo de trabalho:
# Training: collect class-loading and object data
java -XX:AOTCacheOutput=app.aot -jar yourapp.jar
# Production: reuse the same cache with ZGC
java -XX:+UseZGC -XX:AOTCache=app.aot -jar yourapp.jar
# or with G1 (the default)
java -XX:AOTCache=app.aot -jar yourapp.jar
Exemplo do Spring Boot (da documentação do JDK): melhoria de 41% no tempo de inicialização do PetClinic (21.000 classes pré-carregadas).
JEP 522: G1 GC: melhorar o rendimento reduzindo a sincronização [FINAL]
O que é: Barreiras de escrita do G1 simplificadas; tabela de cartões dupla elimina a disputa entre os threads do aplicativo e do otimizador de GC. Resultado: ganho de desempenho de 5 a 15% em cargas de trabalho com grande volume de objetos; tempos de pausa ligeiramente menores.
Quando você vai usar: Nada a fazer! As melhorias são automáticas. Acompanhe -XX:+PrintGCDetailsse tiver interesse.
Trecho de teste (das notas de lançamento):
# Before: heavy mutation → GC thread contention
java -XX:+UseG1GC -XX:+PrintGCDetails -jar cpu-intensive-app.jar
# After Java 26: same flags, lower GC overhead
java -XX:+UseG1GC -XX:+PrintGCDetails -jar cpu-intensive-app.jar
# Observe: fewer GC pauses, higher throughput
JEP 517: HTTP/3 para a API do Cliente HTTP [FINAL]
O que é: HttpClientagora suporta HTTP/3 (sobre QUIC). Benefícios: handshakes mais rápidos, sem bloqueio de cabeçalho de fila, resiliente em redes com alta perda de pacotes. Ativação opcional; o padrão é HTTP/2 para compatibilidade.
Quando usar: Ao servir conteúdo de endpoints compatíveis com HTTP/3 (CDNs modernos, balanceadores de carga na nuvem). Compatível com versões anteriores; código existente inalterado.
Código (opt-in HTTP/3 explícito):
// src/main/java/com/loiane/http/Http3Client.java
package com.loiane.http;
import java.net.http.*;
import java.net.URI;
public class Http3Client {
public static void main(String[] args) throws Exception {
// Default HTTP/2 client
var client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2)
.build();
var req = HttpRequest.newBuilder(
URI.create("https://example.com/api/data"))
.GET()
.build();
var resp = client.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println("Status: " + resp.statusCode());
System.out.println("Body: " + resp.body());
// HTTP/3 client: opt-in
var h3Client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_3)
.build();
var h3Resp = h3Client.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println("HTTP/3 Status: " + h3Resp.statusCode());
// If server doesn't support HTTP/3, transparently falls back to HTTP/2
}
}
Computação vetorial (incubação inicial)
JEP 529: API vetorial [INCUBADORA]
O que é: Expressões de operações vetoriais (SIMD) que compilam de forma confiável para AVX, NEON ou SVE. Servem como base VectorSpeciespara definir formato e tamanho; o HotSpot C2 compila para instruções vetoriais de hardware.
Quando usar: Aprendizado de máquina, criptografia, computação numérica, hashing de arrays. Ainda não está pronto para uso geral (em fase de incubação, aguardando o Projeto Valhalla); usado internamente no JDK.
Esboço de código (adição vetorial):
// src/main/java/com/loiane/compute/VectorSum.java
package com.loiane.compute;
import jdk.incubator.vector.*;
public class VectorSum {
static final VectorSpecies<Float> SPECIES = FloatVector.SPECIES_PREFERRED;
static float[] addVectors(float[] a, float[] b) {
float[] c = new float[a.length];
int i = 0;
// Vectorized loop
int upperBound = SPECIES.loopBound(a.length);
for (; i < upperBound; i += SPECIES.length()) {
FloatVector va = FloatVector.fromArray(SPECIES, a, i);
FloatVector vb = FloatVector.fromArray(SPECIES, b, i);
FloatVector vc = va.add(vb);
vc.intoArray(c, i);
}
// Scalar tail
for (; i < a.length; i++) {
c[i] = a[i] + b[i];
}
return c;
}
public static void main(String[] args) {
float[] a = {1.0f, 2.0f, 3.0f, 4.0f};
float[] b = {5.0f, 6.0f, 7.0f, 8.0f};
float[] c = addVectors(a, b);
for (float v : c) System.out.println(v);
}
}
Compile (add-modules for incubator):
javac --add-modules jdk.incubator.vector -d out \
src/main/java/com/loiane/compute/VectorSum.java
java --add-modules jdk.incubator.vector -cp out com.loiane.compute.VectorSum
Em CPUs que suportam AVX-512 (por exemplo, Xeon), o HotSpot gera instruções vetorizadas; em CPUs mais antigas, o processo é revertido automaticamente.
Limpeza da plataforma
JEP 504: Remover a API Applet [FINAL]
O que é: java.applet, javax.swing.JApplet, e classes relacionadas foram completamente removidas . Applets não funcionam em navegadores há mais de 10 anos.
Lembra dos aplicativos bancários do início dos anos 2000? Todos eles eram baseados em Applets!
Quando você será afetado: Somente se você mantiver código legado usando applets. Caminho de migração:
- Contêineres de interface do usuário : Use componentes AWT ou Swing diretamente.
- Reprodução de áudio : Usar
javax.sound.SoundClip(adicionado no Java 25).
Se você encontrar erros de compilação, significa que está modernizando. Isso é progresso.
O que você pode começar a usar hoje
Aqui está um roteiro pragmático para a adoção dos recursos do Java 26 em seus projetos:
Pronto para produção (sem necessidade de sinalizadores) [FINAL]
Comece a usar esses recursos imediatamente em qualquer projeto Java 26:
- Suporte a HTTP/3 (JEP 517) : Adicione uma única linha para optar por participar; o código existente não será afetado. Risco zero.
var client = HttpClient.newBuilder() .version(HttpClient.Version.HTTP_3) .build(); - Cache AOT com qualquer GC (JEP 516) : Melhora o desempenho em inicialização a frio em 30 a 40%. Adicione uma etapa de treinamento em sua CI; envie
app.aotpara as imagens de produção. Uma vitória absoluta.java -XX:AOTCacheOutput=app.aot -jar app.jar --train java -XX:AOTCache=app.aot -jar app.jar # Production - Melhorias no G1 GC (JEP 522) : Automático. Nada a fazer; aproveite um ganho de desempenho de 5 a 15% em cargas de trabalho com grande quantidade de objetos.
- Avisos de campos finais (JEP 500) : Analise os avisos nos logs; coordene com as atualizações de dependências. Nenhuma ação imediata é necessária, a menos que se utilize reflexão profunda nos campos finais.
Seguro para adoção em desenvolvimento/teste [PRÉVIA]
Essas funcionalidades são estáveis e serão implementadas em breve. Use-as em desenvolvimento e testes; planeje a implementação em produção quando estiverem finalizadas.
- Padrões de tipo primitivo (JEP 530) : Quarta prévia; caminho claro para a finalização. Adote em novos códigos e refatore bases de código com alta dependência de recursos avançados.
if (value instanceof int x) { ... } switch (price) { case long l when l > 10_000 -> "PREMIUM"; ... }Adicionar ao pipeline de construção:
javac --enable-preview --release 26. - Concorrência estruturada (JEP 525) : Sexta prévia; comprovada em aplicações reais. Use para todo novo código concorrente.
try (var scope = StructuredTaskScope.open(Joiner.allSuccessfulOrThrow())) { var t1 = scope.fork(() -> ...); var t2 = scope.fork(() -> ...); scope.join(); return new Result(t1.get(), t2.get()); } - Constantes preguiçosas (JEP 526) : Segunda prévia; API estável. Use para otimizar a inicialização do aplicativo.
static final LazyConstant<Logger> LOGGER = LazyConstant.of(() -> Logger.getLogger("app")); - Codificações PEM (JEP 524) : Segunda prévia; simples. Use para manipulação de chaves/certificados criptográficos:
var kp = KeyPairGenerator.getInstance("RSA").generateKeyPair(); String pem = PEMEncoder.of().encodeToString(kp);
Experimental (incubadoras) — aguardar finalização
- API Vector (JEP 529) : Décima primeira incubadora; depende do Projeto Valhalla. Ainda não recomendada para uso em produção. Acompanhe a conclusão no Java 27/28.
Lista de verificação para migração
Se você é um dos primeiros a adotar o Java 26:
- Ative as pré-visualizações na sua compilação :
<!-- Maven --> <release>26</release> <args> <arg>--enable-preview</arg> </args> - Atualização de CI/CD :
- Baixe o JDK 26 GA.
- Configure a geração de cache AOT nas etapas de treinamento (opcional, mas recomendado).
- Teste
--enable-previewpara detectar depreciações precocemente.
- Refatorar incrementalmente :
- Novo código: usar padrões primitivos, concorrência estruturada e constantes preguiçosas.
- Código legado: adote conforme o tempo permitir; esses recursos não são disruptivos.
- Plano para migração para LTS :
- Java 26 = 6 meses de atualizações (até setembro de 2026).
- ou permaneça usando o Java 21 LTS ou o Java 25 LTS até lá.
Notas
- Os recursos de pré-visualização e incubação exigem
--enable-previewe/ou--add-modules. - Os padrões primitivos (JEP 530) estão na reta final: a quarta prévia sugere a finalização no Java 27 ou 28.
- A concorrência estruturada (JEP 525) também está em um nível de maturidade semelhante; planeje usá-la em novos códigos concorrentes hoje mesmo.
- As constantes preguiçosas e as codificações PEM estão em fase de refinamento; pequenos ajustes na API são possíveis antes da versão final.
- A API Vector deixará de estar em fase de incubação assim que o Projeto Valhalla entregar classes de valor; ainda não é recomendada para produção fora do próprio JDK.
- A implementação final das restrições de campo envolve várias versões: avisos na versão 26 e proibições em uma versão futura. Planeje suas migrações agora.
Referências
- Downloads do JDK 26 GA
- Índice JEP do OpenJDK
- Projeto Leyden: Inicialização e Aquecimento
- Projeto Valhalla: Classes de Valor
Boa programação!




