lang-java
Fornece padrões de engenharia de software em Java moderno (Java 17/21/25 LTS) baseados na documentação oficial (docs.oracle.com/en/java), Java Concurrency in Practice (Goetz) e boas práticas de JVM. C
SKILL.mdskills/languages/lang-java/SKILL.md
GitHubHabilidade de IA: Engenharia de Software em Java (Java Moderno e Concorrência)
Esta skill orienta a inteligência artificial a escrever código Java moderno, idiomático e thread-safe, baseada na documentação oficial Java (JDK 21/25 LTS — docs.oracle.com/en/java) e na obra Java Concurrency in Practice (Brian Goetz et al., Addison-Wesley).
🧭 1. Java Moderno (Linguagem)
- Records: use para dados imutáveis (Value Objects, DTOs). Componha com
recordpatterns para deconstrução segura. - Sealed classes/interfaces: modele hierarquias fechadas (ADTs) combinadas com pattern matching em
switchexaustivo. - Text blocks e switch expressions: prefira
switchcomo expressão (arrows, exaustividade compilada) a cadeias de if/else. - Optional: tipo de retorno de consultas eventualmente vazias; nunca para campos ou parâmetros (anti-padrão).
- Streams: expressam pipelines sobre coleções; cuidado em hot paths (alocação de lambdas/boxes); use loops tradicionais onde o profiler apontar gargalo.
- Var e generics:
varpara tipo óbvio local; escreva generics com PECS (extends/superwildcards corretos) e bounded types. - Imutabilidade por padrão:
finalem campos, classes fecháveis, coleções imutáveis (List.of,Map.copyOf). Imutáveis são thread-safe gratuitos.
🔀 2. Concorrência Segura (Java Concurrency in Practice)
2.1 Estado compartilhado e visibilidade
- Regra de ouro: sempre que mais de um thread acessa um mesmo estado mutável, todas as vias de acesso devem usar o mesmo lock.
- Volatile: garante visibilidade e ordenação (happens-before), não atomicidade composta. Use para flags de parada e publicação segura; nunca para
count++. - Happens-before: monitor locks,
volatile,Thread.start/join,Executor.submit,CompletableFutureestabelecem happens-before; sem ele, reordenações do JIT tornam dados publicados inconsistências (stale data, reordering). - Escape analysis e publicação: publique objetos imutáveis livremente (safe publication); objetos mutáveis exigem synchronization,
finalfields ou fences. - Thread confinement: stack confinement (locais),
ThreadLocal— zero sincronização quando o estado não cruza threads.
2.2 Composição de objetos thread-safe
- Delegação: componha segurança a partir de classes thread-safe (
ConcurrentHashMap,CopyOnWriteArrayList,AtomicLong,BlockingQueue). - Invariantes multi-variáveis (ex:
lower <= upper): exigem um único lock que cubra todos os campos do invariante; delegar por variável quebra o invariante. - Client-side locking frágil: só se o "cliente" souber qual lock a classe usa; prefira extensão por composição.
- Immutability como estratégia: objetos imutáveis podem ser compartilhados sem lock (regra happens-before do campo
final).
2.3 Building blocks (java.util.concurrent)
- Executor framework: nunca crie
Threadcru em produção — desacople submissão de execução comExecutorService(thread pools nomeados,ManagedThreadFactoryem containers). - BlockingQueues (
ArrayBlockingQueue,LinkedBlockingQueue,SynchronousQueue): produtor/consumidor com backpressure natural. - Sincronizadores:
CountDownLatch(aguardar N eventos),Semaphore(limitar acesso),CyclicBarrier(pontos de sincronização),Phaser(fases). - ConcurrentHashMap: não sincronize manualmente o mapa; use
compute,computeIfAbsent,putIfAbsentpara atomicidade por chave. - CompletableFuture: composição assíncrona não-bloqueante (
thenApply/thenCompose/thenCombine,orTimeout); eviteget()sem timeout.
2.4 Task execution e pools
- Tamanho do pool: CPU-bound ≈
Runtime.availableProcessors(); IO-bound ≈cores × (1 + wait/compute). Prefira filas limitadas (ArrayBlockingQueue) + política de saturação (CallerRunsPolicypara degenerar graciosamente, ou rejeição com backpressure). - Executores da plataforma vs
newVirtualThreadPerTaskExecutor: I/O-intensivo com milhões de tarefas → Virtual Threads; CPU-intensivo → pool fixo de Platform Threads. - Encontre o paralelismo explorável (Lei de Amdahl): adicionar threads além dos núcleos de CPU não acelera cargas CPU-bound; adiciona contaminação de cache e trocas de contexto.
2.5 Cancellation, shutdown e liveness
- Cooperação: implemente cancelamento via interruption (
Thread.interrupt, checks periódicos deisInterrupted) ou flagvolatilede cancelamento. - Time-outs em todas as blocking calls; nunca
Thread.stop/suspend(deprecadas/destrutivas). - Deadlock (lock-ordering cycles): ordene aquisição de locks globalmente; alternativas com
tryLocktimeout (recuperação sem deadlock). - Starvation e livelock: evite prioridades de thread; fairness (
new ReentrantLock(true)) só onde estritamente necessário. - Shutdown gracioso:
shutdown()+awaitTermination+ "shutdown hooks" para estados persistentes.
2.6 Competição e performance
- Reduza contenção: escopo do lock curto, lock striping/concurrent collections, copy-on-write para read-heavy, atômicos (CAS) em contadores leves (
LongAdderem alta contenção). - Nonblocking algorithms (CAS/lock-free):
AtomicReference/AtomicStampedReference(ABA com versionamento); prefira bibliotecas maduras (JCTools, Agrona) a lock-free caseiro. - False sharing: pad fields compartilhados entre threads em cache lines distintas (
@Contended/jdk.internal.vm.annotation ou padding manual).
🧵 3. Virtual Threads (Project Loom, JDK 21+)
Baseado na documentação oficial (docs.oracle.com/en/java/javase/21/core/virtual-threads.html, JEP 444):
- O que são: instâncias de
java.lang.Threadimplementadas pelo runtime Java (não pelo SO), mapeando milhões de threads virtuais em poucos carrier threads de plataforma. Bloqueio de I/O suspende (unmount) a thread virtual, liberando o carrier. - Fornecem escala (throughput), não velocidade (latência): não executam código mais rápido que platform threads; existem para ampliar concorrência em servidores thread-per-request.
- Quando usar: altíssimo throughput concorrente com tarefas majoritariamente bloqueadas em I/O (HTTP, JDBC); não para tarefas CPU-intensivas ou longas.
- Escreva código síncrono simples com I/O bloqueante: o estilo thread-per-request com APIs bloqueantes é o que mais se beneficia; evite misturar código bloqueante síncrono com frameworks assíncronos (Callbacks/CompletableFuture encadeado não se beneficia).
- Nunca faça pool de virtual threads: crie um executor por tarefa com
Executors.newVirtualThreadPerTaskExecutor()(leve, fechável com try-with-resources). O número de threads virtuais deve igualar o número de tarefas concorrentes, como "strings para nomes". - Use
Semaphorepara limitar concorrência (ex: serviço externo que aceita 10 chamadas simultâneas) em vez de pool de threads — filas de threads bloqueadas são equivalentes a filas de tarefas. Pools de conexão de banco já funcionam como semáforo. - Pinning: uma thread virtual não desmonta do carrier quando bloqueia dentro de bloco/método
synchronizedou métodonative/FFM. Pinning frequente e longo prejudica a escalabilidade.- Detecção: evento JFR
jdk.VirtualThreadPinned(default > 20 ms) ou-Djdk.tracePinnedThreads=full|short. - Correção: troque
synchronizedporReentrantLock(lock.lock(); try { ... } finally { lock.unlock(); }) nos pontos longos; preservesynchronizedem operações curtas/infrequentes.
- Detecção: evento JFR
- ThreadLocal: cuidado com caches de objetos caros em
ThreadLocal(ex:SimpleDateFormat) — com milhões de threads virtuais cada tarefa instancia um objeto novo (o oposto do efeito desejado). Prefira objetos imutáveis compartilhados (DateTimeFormatter) ou Scoped Values. - Observabilidade: dumps com
jcmd <pid> Thread.dump_to_file -format=json <file>; eventos JFRjdk.VirtualThreadStart/End/Pinned/SubmitFailed.
⚡ 4. Tuning de JVM e Boas Práticas de Performance
- GC: G1 (padrão balanceado), ZGC/Shenandoah (latência de sub-ms com heap grande); dimensione
-Xms/-Xmxiguais em produção; monitore pausas e frequência de full GC. - JIT: métodos pequenos quentes são inlinados; evite megamorphic call sites (mantenha bimorphic), métodos frios grandes quebram inlining.
- Medidas: microbenchmarks com JMH (forks, warmup, blackhole); nunca
System.nanoTimeavulso; profilers async-profiler/flamegraphs para CPU e alocação. - Coleções: escolha pelo perfil de acesso (
HashMapvsConcurrentHashMap,ArrayDequeem vez deStack,EnumMaptipados); sized adequadamente (initialCapacity) evita rehash. - Strings e I/O:
StringBuilderem loops; buffers com size adequado; UTF-8 explícito.
🧪 5. Protocolo de Implementação e Revisão (Java)
- Modele o estado compartilhado: identifique variáveis mutáveis compartilhadas e escolha a estratégia (imutável > confinement > concurrent collection > lock).
- Desacople tarefas com Executors: defina política (pool size, fila, saturação, naming, context propagation) documentada.
- Prove a thread-safety: invariante identificado + mecanismo que o protege + teste de estresse concorrente (ex: jcstress para algoritmos avançados).
- Prefira APIs de alto nível (
java.util.concurrent) a primitivas (synchronized/wait/notify) quebradas à mão. - Instrumente e meça: latência p99, GC, contention (jstack, JFR, jitwatch) antes/depois da mudança.
- Documente: estados compartilhados com o lock/guard que os protege, razões de invariante e política de shutdown.
🧼 6. Java Distiller: Refatoração, Modernização e Código Idiomático (Java 21/25)
Inspirado nos princípios do Java Distiller da comunidade SouJava, aplique a simplificação rigorosa e a eliminação de complexidade acidental:
6.1 Transformações Canônicas de Modernização
- POJO / JavaBean para Record:
- Substitua classes de transporte de dados verbosas (getters, setters, equals, hashCode manuais) por
record. - Utilize deconstrução com Record Patterns:
if (response instanceof SuccessResponse(var payload, var timestamp)) { process(payload); }
- Substitua classes de transporte de dados verbosas (getters, setters, equals, hashCode manuais) por
- Loops Imperativos para Stream Pipelines & Gatherers:
- Converta loops com acumuladores e mutação de listas para Streams declarativos:
// Antes: loop imperativo acumulador // Depois: var activeNames = users.stream() .filter(User::isActive) .map(User::name) .toList();
- Converta loops com acumuladores e mutação de listas para Streams declarativos:
- Switch Expressions & Sealed Hierarchies:
- Elimine árvores de
instanceofe casts manuais. Useswitchexaustivo com type pattern matching:return switch (event) { case OrderCreated e -> handleCreated(e); case OrderCancelled e -> handleCancelled(e); };
- Elimine árvores de
- Legado Date/Calendar para
java.time:- Elimine
java.util.Date,CalendareSimpleDateFormat(não thread-safe). UseInstant,LocalDate,ZonedDateTimeeDateTimeFormatter.
- Elimine
- Eliminação de Código Prolixo ("Distill, don'''t decorate"):
- Remova abstrações intermediárias que apenas delegam chamadas sem agregar valor de domínio.
- Preserve comportamento funcional idêntico com menos linhas e maior expressividade.
🔗 Integração com Outras Skills
- jpa-hibernate-performance: persistência eficiente (N+1, batching, cache) em Java.
- backend-developer: integração de serviços e APIs com contratos REST/gRPC.
- latency-engineering: sizing de thread pools com Little's Law e redução de lock contention.
- lang-python e python-performance-parallelism: equivalentes de concorrência em Python (GIL vs Loom).
- code-optimizer: o agente de otimização orquestra esta skill em refatorações Java.