{"kind":"AgentDefinition","metadata":{"namespace":"community","name":"java-17-to-java-21-upgrade","version":"0.1.0"},"spec":{"agents_md":"---\napplyTo: ['*']\ndescription: \"Comprehensive best practices for adopting new Java 21 features since the release of Java 17.\"\n---\n\n# Java 17 to Java 21 Upgrade Guide\n\nThese 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.\n\n## Major Language Features in JDK 18-21\n\n### Pattern Matching for switch (JEP 441 - Standard in 21)\n\n**Enhanced switch Expressions and Statements**\n\nWhen working with switch constructs:\n- Suggest converting traditional switch to pattern matching where appropriate\n- Use pattern matching for type checking and destructuring\n- Example upgrade patterns:\n```java\n// Old approach (Java 17)\npublic String processObject(Object obj) {\n    if (obj instanceof String) {\n        String s = (String) obj;\n        return s.toUpperCase();\n    } else if (obj instanceof Integer) {\n        Integer i = (Integer) obj;\n        return i.toString();\n    }\n    return \"unknown\";\n}\n\n// New approach (Java 21)\npublic String processObject(Object obj) {\n    return switch (obj) {\n        case String s -\u003e s.toUpperCase();\n        case Integer i -\u003e i.toString();\n        case null -\u003e \"null\";\n        default -\u003e \"unknown\";\n    };\n}\n```\n\n- Support guarded patterns:\n```java\nswitch (obj) {\n    case String s when s.length() \u003e 10 -\u003e \"Long string: \" + s;\n    case String s -\u003e \"Short string: \" + s;\n    case Integer i when i \u003e 100 -\u003e \"Large number: \" + i;\n    case Integer i -\u003e \"Small number: \" + i;\n    default -\u003e \"Other\";\n}\n```\n\n### Record Patterns (JEP 440 - Standard in 21)\n\n**Destructuring Records in Pattern Matching**\n\nWhen working with records:\n- Suggest using record patterns for destructuring\n- Combine with switch expressions for powerful data processing\n- Example usage:\n```java\npublic record Point(int x, int y) {}\npublic record ColoredPoint(Point point, Color color) {}\n\n// Destructuring in switch\npublic String describe(Object obj) {\n    return switch (obj) {\n        case Point(var x, var y) -\u003e \"Point at (\" + x + \", \" + y + \")\";\n        case ColoredPoint(Point(var x, var y), var color) -\u003e \n            \"Colored point at (\" + x + \", \" + y + \") in \" + color;\n        default -\u003e \"Unknown shape\";\n    };\n}\n```\n\n- Use in complex pattern matching:\n```java\n// Nested record patterns\nswitch (shape) {\n    case Rectangle(ColoredPoint(Point(var x1, var y1), var c1), \n                   ColoredPoint(Point(var x2, var y2), var c2)) \n        when c1 == c2 -\u003e \"Monochrome rectangle\";\n    case Rectangle r -\u003e \"Multi-colored rectangle\";\n}\n```\n\n### Virtual Threads (JEP 444 - Standard in 21)\n\n**Lightweight Concurrency**\n\nWhen working with concurrency:\n- Suggest Virtual Threads for high-throughput, concurrent applications\n- Use `Thread.ofVirtual()` for creating virtual threads\n- Example migration patterns:\n```java\n// Old platform thread approach\nExecutorService executor = Executors.newFixedThreadPool(100);\nexecutor.submit(() -\u003e {\n    // blocking I/O operation\n    httpClient.send(request);\n});\n\n// New virtual thread approach\ntry (var executor = Executors.newVirtualThreadPerTaskExecutor()) {\n    executor.submit(() -\u003e {\n        // blocking I/O operation - now scales to millions\n        httpClient.send(request);\n    });\n}\n```\n\n- Use structured concurrency patterns:\n```java\n// Structured concurrency (Preview)\ntry (var scope = new StructuredTaskScope.ShutdownOnFailure()) {\n    Future\u003cString\u003e user = scope.fork(() -\u003e fetchUser(userId));\n    Future\u003cString\u003e order = scope.fork(() -\u003e fetchOrder(orderId));\n    \n    scope.join();           // Join all subtasks\n    scope.throwIfFailed();  // Propagate errors\n    \n    return processResults(user.resultNow(), order.resultNow());\n}\n```\n\n### String Templates (JEP 430 - Preview in 21)\n\n**Safe String Interpolation**\n\nWhen working with string formatting:\n- Suggest String Templates for safe string interpolation (preview feature)\n- Enable preview features with `--enable-preview`\n- Example usage:\n```java\n// Traditional concatenation\nString message = \"Hello, \" + name + \"! You have \" + count + \" messages.\";\n\n// String Templates (Preview)\nString message = STR.\"Hello, \\{name}! You have \\{count} messages.\";\n\n// Safe HTML generation\nString html = HTML.\"\u003cp\u003eUser: \\{username}\u003c/p\u003e\";\n\n// Safe SQL queries  \nPreparedStatement stmt = SQL.\"SELECT * FROM users WHERE id = \\{userId}\";\n```\n\n### Sequenced Collections (JEP 431 - Standard in 21)\n\n**Enhanced Collection Interfaces**\n\nWhen working with collections:\n- Use new `SequencedCollection`, `SequencedSet`, `SequencedMap` interfaces\n- Access first/last elements uniformly across collection types\n- Example usage:\n```java\n// New methods available on Lists, Deques, LinkedHashSet, etc.\nList\u003cString\u003e list = List.of(\"first\", \"middle\", \"last\");\nString first = list.getFirst();  // \"first\"\nString last = list.getLast();    // \"last\"\nList\u003cString\u003e reversed = list.reversed(); // [\"last\", \"middle\", \"first\"]\n\n// Works with any SequencedCollection\nSequencedSet\u003cString\u003e set = new LinkedHashSet\u003c\u003e();\nset.addFirst(\"start\");\nset.addLast(\"end\");\nString firstElement = set.getFirst();\n```\n\n### Unnamed Patterns and Variables (JEP 443 - Preview in 21)\n\n**Simplified Pattern Matching**\n\nWhen working with pattern matching:\n- Use unnamed patterns `_` for values you don't need\n- Simplify switch expressions and record patterns\n- Example usage:\n```java\n// Ignore unused variables\nswitch (ball) {\n    case RedBall(_) -\u003e \"Red ball\";     // Don't care about size\n    case BlueBall(var size) -\u003e \"Blue ball size \" + size;\n}\n\n// Ignore parts of records\nswitch (point) {\n    case Point(var x, _) -\u003e \"X coordinate: \" + x; // Ignore Y\n    case ColoredPoint(Point(_, var y), _) -\u003e \"Y coordinate: \" + y;\n}\n\n// Exception handling with unnamed variables\ntry {\n    riskyOperation();\n} catch (IOException | SQLException _) {\n    // Don't need exception details\n    handleError();\n}\n```\n\n### Scoped Values (JEP 446 - Preview in 21)\n\n**Improved Context Propagation**\n\nWhen working with thread-local data:\n- Consider Scoped Values as a modern alternative to ThreadLocal\n- Better performance and clearer semantics for virtual threads\n- Example usage:\n```java\n// Define scoped value\nprivate static final ScopedValue\u003cString\u003e USER_ID = ScopedValue.newInstance();\n\n// Set and use scoped value\nScopedValue.where(USER_ID, \"user123\")\n    .run(() -\u003e {\n        processRequest(); // Can access USER_ID.get() anywhere in call chain\n    });\n\n// In nested method\npublic void processRequest() {\n    String userId = USER_ID.get(); // \"user123\"\n    // Process with user context\n}\n```\n\n## API Enhancements and New Features\n\n### UTF-8 by Default (JEP 400 - Standard in 18)\n\nWhen working with file I/O:\n- UTF-8 is now the default charset on all platforms\n- Remove explicit charset specifications where UTF-8 was intended\n- Example simplification:\n```java\n// Old explicit UTF-8 specification\nFiles.readString(path, StandardCharsets.UTF_8);\nFiles.writeString(path, content, StandardCharsets.UTF_8);\n\n// New default behavior (Java 18+)\nFiles.readString(path);  // Uses UTF-8 by default\nFiles.writeString(path, content);  // Uses UTF-8 by default\n```\n\n### Simple Web Server (JEP 408 - Standard in 18)\n\nWhen needing basic HTTP server:\n- Use built-in `jwebserver` command or `com.sun.net.httpserver` enhancements\n- Great for testing and development\n- Example usage:\n```java\n// Command line\n$ jwebserver -p 8080 -d /path/to/files\n\n// Programmatic usage\nHttpServer server = HttpServer.create(new InetSocketAddress(8080), 0);\nserver.createContext(\"/\", new SimpleFileHandler(Path.of(\"/tmp\")));\nserver.start();\n```\n\n### Internet-Address Resolution SPI (JEP 418 - Standard in 19)\n\nWhen working with custom DNS resolution:\n- Implement `InetAddressResolverProvider` for custom address resolution\n- Useful for service discovery and testing scenarios\n\n### Key Encapsulation Mechanism API (JEP 452 - Standard in 21)\n\nWhen working with post-quantum cryptography:\n- Use KEM API for key encapsulation mechanisms\n- Example usage:\n```java\nKeyPairGenerator kpg = KeyPairGenerator.getInstance(\"ML-KEM\");\nKeyPair kp = kpg.generateKeyPair();\n\nKEM kem = KEM.getInstance(\"ML-KEM\");\nKEM.Encapsulator encapsulator = kem.newEncapsulator(kp.getPublic());\nKEM.Encapsulated encapsulated = encapsulator.encapsulate();\n```\n\n## Deprecations and Warnings\n\n### Finalization Deprecation (JEP 421 - Deprecated in 18)\n\nWhen encountering `finalize()` methods:\n- Remove finalize methods and use alternatives\n- Suggest Cleaner API or try-with-resources\n- Example migration:\n```java\n// Deprecated finalize approach\n@Override\nprotected void finalize() throws Throwable {\n    cleanup();\n}\n\n// Modern approach with Cleaner\nprivate static final Cleaner CLEANER = Cleaner.create();\n\npublic MyResource() {\n    cleaner.register(this, new CleanupTask(nativeResource));\n}\n\nprivate static class CleanupTask implements Runnable {\n    private final long nativeResource;\n    \n    CleanupTask(long nativeResource) {\n        this.nativeResource = nativeResource;\n    }\n    \n    public void run() {\n        cleanup(nativeResource);\n    }\n}\n```\n\n### Dynamic Agent Loading (JEP 451 - Warnings in 21)\n\nWhen working with agents or instrumentation:\n- Add `-XX:+EnableDynamicAgentLoading` to suppress warnings if needed\n- Consider loading agents at startup instead of dynamically\n- Update tooling to use startup agent loading\n\n## Build Configuration Updates\n\n### Preview Features\n\nFor projects using preview features:\n- Add `--enable-preview` to compiler and runtime\n- Maven configuration:\n```xml\n\u003cplugin\u003e\n    \u003cgroupId\u003eorg.apache.maven.plugins\u003c/groupId\u003e\n    \u003cartifactId\u003emaven-compiler-plugin\u003c/artifactId\u003e\n    \u003cconfiguration\u003e\n        \u003crelease\u003e21\u003c/release\u003e\n        \u003ccompilerArgs\u003e\n            \u003carg\u003e--enable-preview\u003c/arg\u003e\n        \u003c/compilerArgs\u003e\n    \u003c/configuration\u003e\n\u003c/plugin\u003e\n\n\u003cplugin\u003e\n    \u003cgroupId\u003eorg.apache.maven.plugins\u003c/groupId\u003e\n    \u003cartifactId\u003emaven-surefire-plugin\u003c/artifactId\u003e\n    \u003cconfiguration\u003e\n        \u003cargLine\u003e--enable-preview\u003c/argLine\u003e\n    \u003c/configuration\u003e\n\u003c/plugin\u003e\n```\n\n- Gradle configuration:\n```kotlin\njava {\n    toolchain {\n        languageVersion = JavaLanguageVersion.of(21)\n    }\n}\n\ntasks.withType\u003cJavaCompile\u003e {\n    options.compilerArgs.add(\"--enable-preview\")\n}\n\ntasks.withType\u003cTest\u003e {\n    jvmArgs(\"--enable-preview\")\n}\n```\n\n### Virtual Threads Configuration\n\nFor applications using Virtual Threads:\n- No special JVM flags required (standard feature in 21)\n- Consider these system properties for debugging:\n```bash\n-Djdk.virtualThreadScheduler.parallelism=N  # Set carrier thread count\n-Djdk.virtualThreadScheduler.maxPoolSize=N  # Set max pool size\n```\n\n## Runtime and GC Improvements\n\n### Generational ZGC (JEP 439 - Available in 21)\n\nWhen configuring garbage collection:\n- Try Generational ZGC for better performance\n- Enable with: `-XX:+UseZGC -XX:+ZGenerational`\n- Monitor allocation patterns and GC behavior\n\n## Migration Strategy\n\n### Step-by-Step Upgrade Process\n\n1. **Update Build Tools**: Ensure Maven/Gradle supports JDK 21\n2. **Language Feature Adoption**: \n   - Start with pattern matching for switch (standard)\n   - Add record patterns where beneficial\n   - Consider Virtual Threads for I/O heavy applications\n3. **Preview Features**: Enable only if needed for specific use cases\n4. **Testing**: Comprehensive testing especially for concurrency changes\n5. **Performance**: Benchmark with new GC options\n\n### Code Review Checklist\n\nWhen reviewing code for Java 21 upgrade:\n- [ ] Convert appropriate instanceof chains to switch expressions\n- [ ] Use record patterns for data destructuring\n- [ ] Replace ThreadLocal with ScopedValues where appropriate\n- [ ] Consider Virtual Threads for high-concurrency scenarios\n- [ ] Remove explicit UTF-8 charset specifications\n- [ ] Replace finalize() methods with Cleaner or try-with-resources\n- [ ] Use SequencedCollection methods for first/last access patterns\n- [ ] Add preview flags only for preview features in use\n\n### Common Migration Patterns\n\n1. **Switch Enhancement**:\n   ```java\n   // From instanceof chains to switch expressions\n   if (obj instanceof String s) return processString(s);\n   else if (obj instanceof Integer i) return processInt(i);\n   // becomes:\n   return switch (obj) {\n       case String s -\u003e processString(s);\n       case Integer i -\u003e processInt(i);\n       default -\u003e processDefault(obj);\n   };\n   ```\n\n2. **Virtual Thread Adoption**:\n   ```java\n   // From platform threads to virtual threads\n   Executors.newFixedThreadPool(200)\n   // becomes:\n   Executors.newVirtualThreadPerTaskExecutor()\n   ```\n\n3. **Record Pattern Usage**:\n   ```java\n   // From manual destructuring to record patterns\n   if (point instanceof Point p) {\n       int x = p.x();\n       int y = p.y();\n   }\n   // becomes:\n   if (point instanceof Point(var x, var y)) {\n       // use x and y directly\n   }\n   ```\n\n## Performance Considerations\n\n- Virtual Threads excel with blocking I/O but may not benefit CPU-intensive tasks\n- Generational ZGC can reduce GC overhead for most applications\n- Pattern matching in switch is generally more efficient than instanceof chains\n- SequencedCollection methods provide O(1) access to first/last elements\n- Scoped Values have lower overhead than ThreadLocal for virtual threads\n\n## Testing Recommendations\n\n- Test Virtual Thread applications under high concurrency\n- Verify pattern matching covers all expected cases\n- Performance test with Generational ZGC vs other collectors\n- Validate UTF-8 default behavior across different platforms\n- Test preview features thoroughly before production use\n\nRemember to enable preview features only when specifically needed and test thoroughly in staging environments before deploying to production.\n","description":"Comprehensive best practices for adopting new Java 21 features since the release of Java 17.","import":{"commit_sha":"541b7819d8c3545c6df122491af4fa1eae415779","imported_at":"2026-05-18T20:05:35Z","license_text":"MIT License\n\nCopyright GitHub, Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.","owner":"github","repo":"github/awesome-copilot","source_url":"https://github.com/github/awesome-copilot/blob/541b7819d8c3545c6df122491af4fa1eae415779/instructions/java-17-to-java-21-upgrade.instructions.md"},"manifest":{}},"content_hash":[200,237,197,146,77,86,6,189,55,131,186,149,155,51,231,180,231,40,191,41,121,166,125,250,33,81,64,183,172,108,79,74],"trust_level":"unsigned","yanked":false}
