Skip to content

feat: Add automatic JDK 25 virtual thread support and simplify executor handling#227

Open
brunoborges wants to merge 3 commits into
mainfrom
refactor/simplify-executor-handling
Open

feat: Add automatic JDK 25 virtual thread support and simplify executor handling#227
brunoborges wants to merge 3 commits into
mainfrom
refactor/simplify-executor-handling

Conversation

@brunoborges
Copy link
Copy Markdown
Collaborator

This PR adds automatic virtual thread support on JDK 25+ and eliminates executor null-checking code smell throughout the SDK.

Summary

Addresses two code smell issues identified in executor handling:

  1. Redundant null checks in CopilotClient (lines 189, 330)
  2. Complex fallback logic in constructor (lines 159-163)

Changes

Multi-Release JAR for Virtual Threads

  • Added DefaultExecutorProvider with platform-specific implementations
  • Maven builds with JDK 25 to generate proper multi-release JAR
  • JAR manifest includes Multi-Release: true

Code Simplification

Eliminated redundant ternary null checks by ensuring executor is never null.

Documentation

  • Removed manual virtual thread instructions from README quick start
  • Updated requirements to explain automatic JDK 25+ virtual thread usage

Testing

  • Added DefaultExecutorProviderTest with multi-release JAR validation
  • Fixed JaCoCo to exclude multi-release classes from coverage
  • All 1005 tests pass

Benefits

  • Cleaner code without redundant null checks
  • Automatic virtual threads on JDK 25+ (no user action required)
  • Backward compatible with Java 17+
  • Proper lifecycle management

…or handling

This commit adds automatic virtual thread support on JDK 25+ via multi-release
JAR and eliminates executor null-checking code smell throughout the SDK.

**Key Changes:**

1. **Multi-Release JAR Support for Virtual Threads**
   - Added `DefaultExecutorProvider` with Java 17 base (returns ForkJoinPool.commonPool())
   - Added Java 25 multi-release version (returns virtual thread executor)
   - Updated Maven build to compile Java 25 version into META-INF/versions/25
   - Updated workflows to build with JDK 25 for proper multi-release JAR generation

2. **Eliminated Executor Null Checks**
   - Removed redundant ternary checks in CopilotClient (lines 189, 330)
   - Simplified constructor logic for executor initialization
   - Executor field is now guaranteed non-null

3. **Documentation Updates**
   - Removed manual virtual thread instructions from README quick start
   - Updated requirements to explain automatic JDK 25+ virtual thread usage
   - Simplified smoke test workflow (no longer modifies sample code)

4. **Test Coverage**
   - Added DefaultExecutorProviderTest with multi-release JAR validation
   - Fixed JaCoCo to exclude multi-release classes from coverage
   - All 1005 tests pass

**Benefits:**
- Cleaner, more maintainable code without null checks
- Automatic virtual thread adoption on JDK 25+ (no user action required)
- Backward compatible with Java 17+
- SDK manages executor lifecycle properly

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 26, 2026 17:05
Since executor is now guaranteed to be non-null, removed redundant
null checks on lines 442 and 530 before calling session.setExecutor().

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a multi-release JAR mechanism to automatically select a virtual-thread-based default executor on JDK 25+, while simplifying executor handling in CopilotClient and updating docs/CI to reflect the new default behavior.

Changes:

  • Add DefaultExecutorProvider with a JDK 25 multi-release implementation returning a virtual-thread-per-task executor.
  • Simplify CopilotClient to always use a non-null executor and introduce shutdown handling for SDK-owned executors.
  • Update Maven/CI configuration and documentation to build/publish with JDK 25 and document automatic virtual thread usage.
Show a summary per file
File Description
src/main/java/com/github/copilot/sdk/CopilotClient.java Centralizes executor selection and introduces executor lifecycle management.
src/main/java/com/github/copilot/sdk/DefaultExecutorProvider.java Provides the default executor implementation for non-JDK25 runtimes.
src/main/java25/com/github/copilot/sdk/DefaultExecutorProvider.java Multi-release JDK 25 implementation that uses virtual threads.
src/main/java/com/github/copilot/sdk/json/CopilotClientOptions.java Updates executor-related Javadoc to describe the new default strategy and ownership.
src/test/java/com/github/copilot/sdk/DefaultExecutorProviderTest.java Adds validation for multi-release behavior and virtual-thread execution on JDK 25.
pom.xml Adds a JDK 25 profile to compile multi-release classes and sets multi-release manifest entry; adjusts JaCoCo excludes.
README.md Updates requirements and removes manual “enable virtual threads” quick start instructions.
src/site/markdown/index.md Syncs documentation requirements with the new automatic virtual-thread default on JDK 25+.
.github/workflows/build-test.yml Runs the main CI test job on JDK 25 to exercise multi-release build output.
.github/workflows/run-smoke-test.yml Updates JDK 25 smoke-test instructions to rely on SDK defaults (no manual edits).
.github/workflows/publish-snapshot.yml Switches snapshot publishing to build with JDK 25.
.github/workflows/publish-maven.yml Switches release publishing to build with JDK 25.

Copilot's findings

  • Files reviewed: 12/12 changed files
  • Comments generated: 2

Comment on lines +161 to +163
this.ownedExecutor = providedExecutor == null && this.executor instanceof ExecutorService executorService
? executorService
: null;
Comment on lines +32 to +36
if (Runtime.version().feature() >= 25) {
return;
}

assertNull(DefaultExecutorProvider.create());
@edburns
Copy link
Copy Markdown
Collaborator

edburns commented May 26, 2026

Hi @brunoborges This PR is a surprise and was not a part of my migration plan https://github.com/github/copilot-sdk-partners/issues/80 . I'll try to get it in, but I must prioritize completing that plan and hitting the GA deadline.

Changed from utility class pattern to enum singleton pattern. This ensures
the executor is created once and reused across all CopilotClient instances,
which is especially beneficial for the virtual thread executor on JDK 25+.

Benefits:
- Single virtual thread executor shared across all clients (more efficient)
- Thread-safe lazy initialization (enum guarantee)
- Prevents instantiation without needing private constructor

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants