一键导入
java-17-to-21
// Upgrade Java projects from JDK 17 to JDK 21 covering Virtual Threads, Pattern Matching for switch, Record Patterns, Sequenced Collections
// Upgrade Java projects from JDK 17 to JDK 21 covering Virtual Threads, Pattern Matching for switch, Record Patterns, Sequenced Collections
| name | java-17-to-21 |
| description | Upgrade Java projects from JDK 17 to JDK 21 covering Virtual Threads, Pattern Matching for switch, Record Patterns, Sequenced Collections |
These instructions help GitHub Copilot assist developers in upgrading Java projects from JDK 17 to JDK 21, focusing on new language features, API changes, and best practices.
Enhanced switch Expressions and Statements
When working with switch constructs:
// Old approach (Java 17)
public String processObject(Object obj) {
if (obj instanceof String) {
String s = (String) obj;
return s.toUpperCase();
} else if (obj instanceof Integer) {
Integer i = (Integer) obj;
return i.toString();
}
return "unknown";
}
// New approach (Java 21)
public String processObject(Object obj) {
return switch (obj) {
case String s -> s.toUpperCase();
case Integer i -> i.toString();
case null -> "null";
default -> "unknown";
};
}
switch (obj) {
case String s when s.length() > 10 -> "Long string: " + s;
case String s -> "Short string: " + s;
case Integer i when i > 100 -> "Large number: " + i;
case Integer i -> "Small number: " + i;
default -> "Other";
}
Destructuring Records in Pattern Matching
When working with records:
public record Point(int x, int y) {}
public record ColoredPoint(Point point, Color color) {}
// Destructuring in switch
public String describe(Object obj) {
return switch (obj) {
case Point(var x, var y) -> "Point at (" + x + ", " + y + ")";
case ColoredPoint(Point(var x, var y), var color) ->
"Colored point at (" + x + ", " + y + ") in " + color;
default -> "Unknown shape";
};
}
// Nested record patterns
switch (shape) {
case Rectangle(ColoredPoint(Point(var x1, var y1), var c1),
ColoredPoint(Point(var x2, var y2), var c2))
when c1 == c2 -> "Monochrome rectangle";
case Rectangle r -> "Multi-colored rectangle";
}
Lightweight Concurrency
When working with concurrency:
Thread.ofVirtual() for creating virtual threads// Old platform thread approach
ExecutorService executor = Executors.newFixedThreadPool(100);
executor.submit(() -> {
// blocking I/O operation
httpClient.send(request);
});
// New virtual thread approach
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
executor.submit(() -> {
// blocking I/O operation - now scales to millions
httpClient.send(request);
});
}
Enhanced Collection Interfaces
When working with collections:
SequencedCollection, SequencedSet, SequencedMap interfaces// New methods available on Lists, Deques, LinkedHashSet, etc.
List<String> list = List.of("first", "middle", "last");
String first = list.getFirst(); // "first"
String last = list.getLast(); // "last"
List<String> reversed = list.reversed(); // ["last", "middle", "first"]
// Works with any SequencedCollection
SequencedSet<String> set = new LinkedHashSet<>();
set.addFirst("start");
set.addLast("end");
String firstElement = set.getFirst();
When working with file I/O:
// Old explicit UTF-8 specification
Files.readString(path, StandardCharsets.UTF_8);
Files.writeString(path, content, StandardCharsets.UTF_8);
// New default behavior (Java 18+)
Files.readString(path); // Uses UTF-8 by default
Files.writeString(path, content); // Uses UTF-8 by default
When needing basic HTTP server:
jwebserver command or com.sun.net.httpserver enhancements// Command line
$ jwebserver -p 8080 -d /path/to/files
// Programmatic usage
HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0);
server.createContext("/", new SimpleFileHandler(Path.of("/tmp")));
server.start();
When working with custom DNS resolution:
InetAddressResolverProvider for custom address resolutionWhen working with post-quantum cryptography:
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ML-KEM");
KeyPair kp = kpg.generateKeyPair();
KEM kem = KEM.getInstance("ML-KEM");
KEM.Encapsulator encapsulator = kem.newEncapsulator(kp.getPublic());
KEM.Encapsulated encapsulated = encapsulator.encapsulate();
When encountering finalize() methods:
// Deprecated finalize approach
@Override
protected void finalize() throws Throwable {
cleanup();
}
// Modern approach with Cleaner
private static final Cleaner CLEANER = Cleaner.create();
public MyResource() {
cleaner.register(this, new CleanupTask(nativeResource));
}
private static class CleanupTask implements Runnable {
private final long nativeResource;
CleanupTask(long nativeResource) {
this.nativeResource = nativeResource;
}
public void run() {
cleanup(nativeResource);
}
}
When working with agents or instrumentation:
-XX:+EnableDynamicAgentLoading to suppress warnings if needed<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<release>21</release>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
tasks.withType<JavaCompile> {
options.release.set(21)
}
tasks.withType<Test> {
useJUnitPlatform()
}
For applications using Virtual Threads:
-Djdk.virtualThreadScheduler.parallelism=N # Set carrier thread count
-Djdk.virtualThreadScheduler.maxPoolSize=N # Set max pool size
When configuring garbage collection:
-XX:+UseZGC -XX:+ZGenerationalWhen reviewing code for Java 21 upgrade:
Switch Enhancement:
// From instanceof chains to switch expressions
if (obj instanceof String s) return processString(s);
else if (obj instanceof Integer i) return processInt(i);
// becomes:
return switch (obj) {
case String s -> processString(s);
case Integer i -> processInt(i);
default -> processDefault(obj);
};
Virtual Thread Adoption:
// From platform threads to virtual threads
Executors.newFixedThreadPool(200)
// becomes:
Executors.newVirtualThreadPerTaskExecutor()
Record Pattern Usage:
// From manual destructuring to record patterns
if (point instanceof Point p) {
int x = p.x();
int y = p.y();
}
// becomes:
if (point instanceof Point(var x, var y)) {
// use x and y directly
}
Remember to test thoroughly in staging environments before deploying to production.
Assess a Java project's modernization posture — Java version, framework versions, dependency health, vulnerabilities, and migration opportunities
Deploy Java applications to Azure services including App Service, Container Apps, AKS, and Spring Apps
Upgrade Java projects from JDK 11 to JDK 17 covering Records, Sealed Classes, Pattern Matching for instanceof, Switch Expressions, Text Blocks
Upgrade Java projects from JDK 21 to JDK 25 covering Flexible Constructor Bodies, Stream Gatherers, Class-File API, Scoped Values, Security Manager removal
Upgrade Java projects from JDK 8 to JDK 11 covering module system, removed Java EE modules (JAXB, JAX-WS, CORBA), var keyword, HTTP Client, collection factory methods
Migrate Java application services and dependencies to Azure equivalents using predefined migration tasks