📖 Sobre o Java 21
Java 21 representa um marco histórico na evolução do Java, sendo a versão LTS mais revolucionária desde o Java 8. Lançado em setembro de 2023, introduz Virtual Threads como feature final, revolucionando programação concorrente, além de String Templates, Pattern Matching avançado e Sequenced Collections. É a versão que moderniza definitivamente o desenvolvimento Java para alta performance e concorrência massiva.
💡 O que são JEPs?
Java 21 incluiu 15 JEPs que consolidaram anos de desenvolvimento em preview features e introduziram inovações que redefinem como escrevemos código Java concorrente e expressivo.
⭐ Principais Novidades
🧵 Concorrência Revolucionária
🔹 JEP 444: Virtual Threads (Final)
❓ O que é?
Threads ultra-leves gerenciadas pela JVM que permitem milhões de threads concorrentes com overhead mínimo, redefinindo completamente programação concorrente em Java.
⚠️ Por que é importante?
Resolve o problema histórico do Java com threads caras do SO. Permite escrever código sequencial simples que escala para milhões de operações concorrentes, especialmente I/O.
// Thread tradicional vs Virtual Thread// Tradicional: cara, limitada (~thousands)Thread traditionalThread = new Thread(() -> { // Consume ~2MB stack memory doWork();});
// Virtual Thread: barata, ilimitada (millions)Thread virtualThread = Thread.ofVirtual().start(() -> { // Consume ~few KB, managed by JVM doWork();});
// Factory methods para Virtual ThreadsThread vt1 = Thread.ofVirtual() .name("worker-1") .start(() -> processTask());
Thread vt2 = Thread.ofVirtual() .name("worker-", 2) // worker-2 .unstarted(() -> processTask());vt2.start();
// Virtual Thread com Executortry (var executor = Executors.newVirtualThreadPerTaskExecutor()) { // Pode criar MILHÕES dessas facilmente! for (int i = 0; i < 1_000_000; i++) { final int taskId = i; executor.submit(() -> { try { // I/O operations não bloqueiam carrier threads Thread.sleep(Duration.ofSeconds(1)); var response = httpClient.send(request, bodyHandler); System.out.println("Task " + taskId + " completed"); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }); }} // Executor fecha automaticamente
// Comparação de performancepublic class PerformanceComparison {
// Approach tradicional - limitado public void traditionalApproach() throws InterruptedException { var executor = Executors.newFixedThreadPool(200); // Máximo prático var latch = new CountDownLatch(10_000);
for (int i = 0; i < 10_000; i++) { executor.submit(() -> { try { // Simula I/O Thread.sleep(100); latch.countDown(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }); }
latch.await(); executor.shutdown(); }
// Virtual Threads - escala infinitamente public void virtualThreadsApproach() throws InterruptedException { var latch = new CountDownLatch(1_000_000); // 100x mais!
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) { for (int i = 0; i < 1_000_000; i++) { executor.submit(() -> { try { // Mesmo I/O, mas não bloqueia carrier threads Thread.sleep(100); latch.countDown(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }); } }
latch.await(); // Roda muito mais rápido! }}🌐 Casos de Uso Práticos
// Web Server com alta concorrênciapublic class HighConcurrencyWebServer {
public void handleRequests() { var server = HttpServer.create();
server.createContext("/api", exchange -> { // Cada request roda em sua própria Virtual Thread Thread.ofVirtual().start(() -> { try { // I/O intensivo não bloqueia outras requests var data = fetchFromDatabase(); var enriched = callExternalAPI(data); var response = processData(enriched);
exchange.sendResponseHeaders(200, response.length()); exchange.getResponseBody().write(response.getBytes()); exchange.close(); } catch (Exception e) { handleError(exchange, e); } }); }); }
// Web Scraping massivo public List<String> scrapeUrls(List<String> urls) { try (var executor = Executors.newVirtualThreadPerTaskExecutor()) { var futures = urls.stream() .map(url -> executor.submit(() -> { // Milhares de requests HTTP concorrentes return httpClient.send( HttpRequest.newBuilder(URI.create(url)).build(), HttpResponse.BodyHandlers.ofString() ).body(); })) .toList();
// Aguardar todos completarem return futures.stream() .map(future -> { try { return future.get(); } catch (Exception e) { return "Error: " + e.getMessage(); } }) .toList(); } }
// Processamento de arquivos em lote public void processLargeDataset(List<Path> files) { try (var executor = Executors.newVirtualThreadPerTaskExecutor()) { var tasks = files.stream() .map(file -> executor.submit(() -> { try { // I/O de arquivo não bloqueia var content = Files.readString(file); var processed = processContent(content); var outputFile = generateOutputPath(file); Files.writeString(outputFile, processed); return outputFile; } catch (IOException e) { throw new UncheckedIOException(e); } })) .toList();
// Aguardar processamento tasks.forEach(task -> { try { var result = task.get(); System.out.println("Processed: " + result); } catch (Exception e) { System.err.println("Error: " + e.getMessage()); } }); } }}⚡ Performance e Características
| Aspecto | Platform Threads | Virtual Threads |
|---|---|---|
| Memória Stack | ~2MB cada | ~few KB cada |
| Limite Prático | ~thousands | millions |
| Criação | Cara (~1ms) | Muito barata (~μs) |
| Context Switch | Caro (kernel) | Muito barato (JVM) |
| I/O Blocking | Bloqueia thread | Não bloqueia carrier |
| Compatibilidade | Código existente | 100% compatível |
📚 Saiba mais: Virtual Threads Guide
🎨 String Templates
🔹 JEP 430: String Templates (Preview)
❓ O que é?
Sistema type-safe de interpolação de strings que permite embedding seguro de expressões e valores diretamente na string, substituindo concatenação verbosa.
⚠️ Por que é importante?
Elimina problemas de SQL injection, oferece melhor performance que concatenação e torna código mais legível e seguro.
// String Template básicoString name = "João Silva";int age = 30;String message = STR."Olá, \{name}! Você tem \{age} anos.";// Resultado: "Olá, João Silva! Você tem 30 anos."
// Expressões complexasdouble price = 19.99;int quantity = 3;double tax = 0.08;String invoice = STR."Total: R$ \{price * quantity * (1 + tax):%.2f}";// Resultado: "Total: R$ 64.77"
// Templates multilinhasString report = STR.""" Relatório de Vendas ================== Cliente: \{name} Idade: \{age} anos Itens: \{quantity} Subtotal: R$ \{price * quantity:%.2f} Taxa: R$ \{price * quantity * tax:%.2f} Total: R$ \{price * quantity * (1 + tax):%.2f} Data: \{LocalDateTime.now().format(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm"))} """;
// Templates para diferentes formatospublic class TemplateExamples {
// JSON seguro public String generateJson(User user) { return STR.""" { "id": \{user.getId()}, "name": "\{user.getName()}", "email": "\{user.getEmail()}", "active": \{user.isActive()}, "lastLogin": "\{user.getLastLogin()?.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)}", "roles": [\{user.getRoles().stream() .map(role -> STR."\"\{role}\"") .collect(Collectors.joining(", "))}] } """; }
// SQL Templates (type-safe!) public String buildQuery(String table, List<String> columns, Map<String, Object> filters) { var columnList = String.join(", ", columns); var whereClause = filters.entrySet().stream() .map(entry -> STR."\{entry.getKey()} = ?\{entry.getValue()}") .collect(Collectors.joining(" AND "));
return STR.""" SELECT \{columnList} FROM \{table} WHERE \{whereClause} ORDER BY created_at DESC """; }
// HTML Templates public String generateCard(Product product) { return STR.""" <div class="product-card"> <h3>\{product.getName()}</h3> <p class="description">\{product.getDescription()}</p> <div class="price"> <span class="currency">R$</span> <span class="amount">\{product.getPrice():%.2f}</span> </div> <div class="stock \{product.getStock() > 0 ? "in-stock" : "out-of-stock"}"> \{product.getStock() > 0 ? STR."\{product.getStock()} disponíveis" : "Fora de estoque"} </div> </div> """; }}🛡️ Templates Customizados
// Template processor customizado para SQLpublic static final StringTemplate.Processor<PreparedStatement, SQLException> SQL = (StringTemplate template) -> { String query = StringTemplate.STR.process(template); return connection.prepareStatement(query); };
// Uso seguro contra SQL injectionpublic List<User> findUsers(String namePattern, int minAge) throws SQLException { PreparedStatement stmt = SQL.""" SELECT * FROM users WHERE name LIKE \{namePattern} AND age >= \{minAge} ORDER BY name """;
// PreparedStatement já configurado! return executeQuery(stmt);}
// Template para logs estruturadospublic static final StringTemplate.Processor<LogEvent, RuntimeException> LOG = (StringTemplate template) -> { // Processa template e cria evento de log estruturado var processed = StringTemplate.STR.process(template); return new LogEvent(Level.INFO, processed, Instant.now()); };
// UsoLogEvent event = LOG."User \{userId} performed action \{action} at \{timestamp}";logger.log(event);🔹 Pattern Matching for Switch (Final)
❓ O que é?
Switch melhorado que suporta pattern matching com qualquer tipo e guards.
💡 Exemplo Simples
// Pattern matching com tipospublic String processValue(Object value) { return switch (value) { case String s when s.length() > 10 -> "String longa: " + s; case String s -> "String curta: " + s; case Integer i when i > 0 -> "Número positivo: " + i; case Integer i -> "Número não positivo: " + i; case null -> "Valor nulo"; default -> "Tipo desconhecido: " + value.getClass(); };}
// Com Recordsrecord Point(int x, int y) {}record Circle(Point center, int radius) {}
public String analyzeShape(Object shape) { return switch (shape) { case Circle(Point(int x, int y), int r) when r > 10 -> STR."Círculo grande em (\{x}, \{y}) com raio \{r}"; case Circle(Point(int x, int y), int r) -> STR."Círculo pequeno em (\{x}, \{y}) com raio \{r}"; case Point(int x, int y) -> STR."Ponto em (\{x}, \{y})"; default -> "Forma desconhecida"; };}🔹 Sequenced Collections
❓ O que é?
Nova interface que representa coleções com ordem definida, oferecendo acesso ao primeiro e último elemento.
💡 Exemplo Simples
// SequencedCollection interfaceList<String> list = List.of("primeiro", "meio", "último");
// Métodos novosString primeiro = list.getFirst(); // "primeiro"String ultimo = list.getLast(); // "último"
// Reversed viewList<String> reverso = list.reversed();// ["último", "meio", "primeiro"]
// Com Set tambémLinkedHashSet<String> set = new LinkedHashSet<>();set.add("a");set.add("b");set.add("c");
String primeiroSet = set.getFirst(); // "a"String ultimoSet = set.getLast(); // "c"🔹 Record Patterns (Final)
❓ O que é?
Permite desestruturar Records diretamente em pattern matching.
💡 Exemplo Simples
record Person(String name, int age) {}record Employee(Person person, String department) {}
public String processEmployee(Employee emp) { return switch (emp) { // Desestruturação aninhada case Employee(Person(String name, int age), String dept) when age < 25 -> STR."\{name} é estagiário em \{dept}"; case Employee(Person(String name, int age), String dept) when age > 50 -> STR."\{name} é sênior em \{dept}"; case Employee(Person(String name, int age), String dept) -> STR."\{name} (\{age} anos) trabalha em \{dept}"; };}🔹 Key Encapsulation Mechanism API
❓ O que é?
API para algoritmos criptográficos quantum-safe, preparando Java para a era pós-quântica.
💡 Exemplo Simples
// Gerar par de chaves para KEMKeyPairGenerator kpg = KeyPairGenerator.getInstance("ML-KEM");KeyPair keyPair = kpg.generateKeyPair();
// Encapsular segredoKEM kem = KEM.getInstance("ML-KEM");KEM.Encapsulator encapsulator = kem.newEncapsulator(keyPair.getPublic());KEM.Encapsulated encapsulated = encapsulator.encapsulate();
byte[] sharedSecret = encapsulated.key();byte[] encapsulation = encapsulated.encapsulation();🔧 Outras Melhorias Importantes
⚡ Performance
- Generational ZGC: Garbage Collection ainda mais eficiente
- Prepare to Restrict Dynamic Loading: Melhor segurança
- Dynamic CDS Archives: Startup mais rápido
🛠️ APIs
- Math.clamp(): Limitar valores a um range
- StringBuilder/StringBuffer repeat(): Repetir sequências
- Emoji support: Melhor suporte a caracteres Unicode
🎯 Impacto e Revolução
Java 21 representa a maior revolução desde Java 8:
- ✅ Virtual Threads eliminam limitações de concorrência
- ✅ String Templates modernizam manipulação de strings
- ✅ Pattern Matching avançado simplifica lógica complexa
- ✅ Sequenced Collections melhoram APIs de coleção
- ✅ Performance excepcional para aplicações I/O intensivas
- ✅ Preparado para futuro quantum-safe
- ✅ Compatibilidade total com código existente
📊 Comparação de LTS
| Aspecto | Java 8 | Java 11 | Java 17 | Java 21 |
|---|---|---|---|---|
| Concorrência | Threads tradicionais | Threads tradicionais | Threads tradicionais | 🚀 Virtual Threads |
| String Templates | ❌ | ❌ | ❌ | ✅ Preview |
| Pattern Matching | ❌ | ❌ | instanceof | ✅ Switch avançado |
| Record Patterns | ❌ | ❌ | ❌ | ✅ Final |
| Sequenced Collections | ❌ | ❌ | ❌ | ✅ Final |
| Quantum-safe Crypto | ❌ | ❌ | ❌ | ✅ KEM API |
| Performance I/O | Thread pools | Thread pools | Thread pools | 🚀 Massivamente escalável |
📅 Informações da Versão
- 📅 Lançamento: 19 de setembro de 2023
- 🔧 Tipo: LTS (Long Term Support)
- ⚡ Suporte Oracle: Até setembro de 2031 (Extended até 2034)
- 🆓 Suporte Gratuito: Eclipse Temurin, Amazon Corretto, Microsoft OpenJDK
- 🎯 Status: LTS revolucionária - nova referência para alta performance
- 🔄 Migração: Fácil - principalmente additive features
🔗 Links Úteis
📚 Documentação Oficial
🧵 Virtual Threads
🎨 String Templates
🔍 Pattern Matching
📚 Collections
🔒 Segurança
💻 Exemplos e Práticas
Arquitetura, código e aprendizado contínuo.