Receber por email
← Voltar para o catálogo

java-migration

Guide for upgrading Java projects between major versions (8→11→17→21→25). Use when user says "upgrade Java", "migrate to Java 25", "update Java version", or when modernizing legacy projects.

638estrelas
Atualizado há 8 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add decebals/claude-code-java

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/java-migration/svg)](https://www.skillteca.com.br/skills/java-migration)
#ai

Alerta por categoria

Receba novas skills de Design e Frontend toda segunda

1 email curto, só com as skills novas de Design e Frontend. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Java Migration Skill

Step-by-step guide for upgrading Java projects between major versions.

When to Use

  • User says "upgrade to Java 25" / "migrate from Java 8" / "update Java version"
  • Modernizing legacy projects
  • Spring Boot 2.x → 3.x → 4.x migration
  • Preparing for LTS version adoption

Migration Paths

Java 8 (LTS) → Java 11 (LTS) → Java 17 (LTS) → Java 21 (LTS) → Java 25 (LTS)
     │              │               │              │               │
     └──────────────┴───────────────┴──────────────┴───────────────┘
                         Always migrate LTS → LTS

Quick Reference: What Breaks

| From → To | Major Breaking Changes | |-----------|------------------------| | 8 → 11 | Removed javax.xml.bind, module system, internal APIs | | 11 → 17 | Sealed classes (preview→final), strong encapsulation | | 17 → 21 | Pattern matching changes, finalize() deprecated for removal | | 21 → 25 | Security Manager removed, Unsafe methods removed, 32-bit dropped |

Migration Workflow

Step 1: Assess Current State

# Check current Java version
java -version

# Check compiler target in Maven
grep -r "maven.compiler" pom.xml

# Find usage of removed APIs
grep -r "sun\." --include="*.java" src/
grep -r "javax\.xml\.bind" --include="*.java" src/

Step 2: Update Build Configuration

Maven:

<properties>
    <java.version>21</java.version>
    <maven.compiler.source>${java.version}</maven.compiler.source>
    <maven.compiler.target>${java.version}</maven.compiler.target>
</properties>

<!-- Or with compiler plugin -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.12.1</version>
    <configuration>
        <release>21</release>
    </configuration>
</plugin>

Gradle:

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
    }
}

Step 3: Fix Compilation Errors

Run compile and fix errors iteratively:

mvn clean compile 2>&1 | head -50

Step 4: Run Tests

mvn test

Step 5: Check Runtime Warnings

# Run with illegal-access warnings
java --illegal-access=warn -jar app.jar

Java 8 → 11 Migration

Removed APIs

| Removed | Replacement | |---------|-------------| | javax.xml.bind (JAXB) | Add dependency: jakarta.xml.bind-api + jaxb-runtime | | javax.activation | Add dependency: jakarta.activation-api | | javax.annotation | Add dependency: jakarta.annotation-api | | java.corba | No replacement (rarely used) | | java.transaction | Add dependency: jakarta.transaction-api | | sun.misc.Base64* | Use java.util.Base64 | | sun.misc.Unsafe (partially) | Use VarHandle where possible |

Add Missing Dependencies (Maven)

<!-- JAXB (if needed) -->
<dependency>
    <groupId>jakarta.xml.bind</groupId>
    <artifactId>jakarta.xml.bind-api</artifactId>
    <version>4.0.1</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>4.0.4</version>
    <scope>runtime</scope>
</dependency>

<!-- Annotation API -->
<dependency>
    <groupId>jakarta.annotation</groupId>
    <artifactId>jakarta.annotation-api</artifactId>
    <version>2.1.1</version>
</dependency>

Module System Issues

If using reflection on JDK internals, add JVM flags:

--add-opens java.base/java.lang=ALL-UNNAMED
--add-opens java.base/java.util=ALL-UNNAMED

Maven Surefire:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
        <argLine>
            --add-opens java.base/java.lang=ALL-UNNAMED
        </argLine>
    </configuration>
</plugin>

New Features to Adopt

// var (local variable type inference)
var list = new ArrayList<String>();  // instead of ArrayList<String> list = ...

// String methods
"  hello  ".isBlank();      // true for whitespace-only
"  hello  ".strip();        // better trim() (Unicode-aware)
"line1\nline2".lines();     // Stream<String>
"ha".repeat(3);             // "hahaha"

// Collection factory methods (Java 9+)
List.of("a", "b", "c");     // immutable list
Set.of(1, 2, 3);            // immutable set
Map.of("k1", "v1");         // immutable map

// Optional improvements
optional.ifPresentOrElse(
    value -> process(value),
    () -> handleEmpty()
);

// HTTP Client (replaces HttpURLConnection)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.example.com"))
    .build();
HttpResponse<String> response = client.send(request,
    HttpResponse.BodyHandlers.ofString());

Java 11 → 17 Migration

Breaking Changes

| Change | Impact | |--------|--------| | Strong encapsulation | --illegal-access no longer works, must use explicit --add-opens | | Sealed classes (final) | If you used preview features | | Pattern matching instanceof | Preview → final syntax change |

New Features to Adopt

// Records (immutable data classes)
public record User(String name, String email) {}
// Auto-generates: constructor, getters, equals, hashCode, toString

// Sealed classes
public sealed class Shape permits Circle, Rectangle {}
public final class Circle extends Shape {}
public final class Rectangle extends Shape {}

// Pattern matching for instanceof
if (obj instanceof String s) {
    System.out.println(s.length());  // s already cast
}

// Switch expressions
String result = switch (day) {
    case MONDAY, FRIDAY -> "Work";
    case SATURDAY, SUNDAY -> "Rest";
    default -> "Midweek";
};

// Text blocks
String json = """
    {
        "name": "John",
        "age": 30
    }
    """;

// Helpful NullPointerException messages
// a.b.c.d() → tells exactly which part was null

Java 17 → 21 Migration

Breaking Changes

| Change | Impact | |--------|--------| | Pattern matching switch (final) | Minor syntax differences from preview | | finalize() deprecated for removal | Replace with Cleaner or try-with-resources | | UTF-8 by default | May affect file reading if assumed platform encoding |

New Features to Adopt

// Virtual Threads (Project Loom) - MAJOR
try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) {
    executor.submit(() -> handleRequest());
}
// Or simply:
Thread.startVirtualThread(() -> doWork());

// Pattern matching in switch
String formatted = switch (obj) {
    case Integer i -> "int: " + i;
    case String s -> "string: " + s;
    case null -> "null value";
    default -> "unknown";
};

// Record patterns
record Point(int x, int y) {}
if (obj instanceof Point(int x, int y)) {
    System.out.println(x + ", " + y);
}

// Sequenced Collections
List<String> list = new ArrayList<>();
list.addFirst("first");    // new method
list.addLast("last");      // new method
list.reversed();           // reversed view

// String templates (preview in 21)
// May need --enable-preview

// Scoped Values (preview) - replace ThreadLocal
ScopedValue<User> CURRENT_USER = ScopedValue.newInstance();
ScopedValue.where(CURRENT_USER, user).run(() -> {
    // CURRENT_USER.get() available here
});

Java 21 → 25 Migration

Breaking Changes

| Change | Impact | |--------|--------| | Security Manager removed | Applications relying on it need alternative security approaches | | sun.misc.Unsafe methods removed | Use VarHandle or FFM API instead | | 32-bit platforms dropped | No more x86-32 support | | Record pattern variables final | Cannot reassign pattern variables in switch | | ScopedValue.orElse(null) disallowed | Must provide non-null default | | Dynamic agents restricted | Requires -XX:+EnableDynamicAgentLoading flag |

Check for Unsafe Usage

# Find sun.misc.Unsafe usage
grep -rn "sun\.misc\.Unsafe" --include="*.java" src/

# Find Security Manager usage
grep -rn 
Compartilhar X LinkedIn