Skip to content

[Java] Add PlatformDetector and NativeRuntimeLoader for native binary extraction and caching (tasks 4.2 + 4.3) - #2157

Open
edburns with Copilot wants to merge 3 commits into
edburns/1917-java-embed-rust-cli-runtime-dd-3039145from
copilot/edburns1917-java-embed-rust-cli-runtime-dd-3039145
Open

[Java] Add PlatformDetector and NativeRuntimeLoader for native binary extraction and caching (tasks 4.2 + 4.3)#2157
edburns with Copilot wants to merge 3 commits into
edburns/1917-java-embed-rust-cli-runtime-dd-3039145from
copilot/edburns1917-java-embed-rust-cli-runtime-dd-3039145

Conversation

Copilot AI commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Implements the PlatformDetector utility (task 4.2) and NativeRuntimeLoader (task 4.3) in the new com.github.copilot.ffi package. Tasks 4.1/4.2 were previously merged as empty commits, so this PR delivers both.

PlatformDetector (ffi/PlatformDetector.java)

Pure-Java classifier detection for selecting the correct runtime.node binary:

  • OS: os.namedarwin | linux | win32
  • Arch: os.arch aliases → x64 | arm64
  • Linux libc: reads /proc/self/exe, parses ELF PT_INTERP segment for musl (/ld-musl-) vs. glibc (/ld-linux-)
  • detectClassifier() → one of 8 validated classifiers (linux-x64, linuxmusl-arm64, darwin-x64, win32-x64, …); unsupported tuples fail fast

NativeRuntimeLoader (ffi/NativeRuntimeLoader.java)

Resolves runtime.node via:

  1. COPILOT_CLI_PATH env var (returned as-is)
  2. Classpath resource native/<classifier>/runtime.node → extracted to ~/.copilot/runtime-cache/<version>/<classifier>/runtime.node
  3. Sibling of bundled CLI

Extraction is atomic: write to a UUID-named temp file in the same directory, Files.move(ATOMIC_MOVE). If another process wins the race, accepts the winner after a regular/non-empty check. No file locks. No execute bit set (JNA dlopen doesn't require it). Abandoned temp files cleaned in finally.

Version is read from copilot-runtime.properties (Maven resource-filtered ${project.version}). A missing, blank, or unfiltered placeholder is a hard error.

// Resolution usage (task 4.4 will pass this path to JNA)
Path runtimeNode = NativeRuntimeLoader.resolve();

Supporting changes

  • copilot-runtime.propertiesversion=${project.version}, filtered at build time
  • pom.xml — Maven <resources> block enables filtering for that one file only
  • NativeRuntimeLoaderException — typed checked exception for all failure modes
  • Test resource native/linux-x64/runtime.node (stub binary for unit tests)

…filtering

Co-authored-by: edburns <75821+edburns@users.noreply.github.com>
Copilot AI changed the title [WIP] Create NativeRuntimeLoader for binary extraction and caching [Java] Add PlatformDetector and NativeRuntimeLoader for native binary extraction and caching (tasks 4.2 + 4.3) Jul 30, 2026
Copilot AI requested a review from edburns July 30, 2026 02:30
@github-actions

This comment has been minimized.

@edburns
edburns marked this pull request as ready for review July 30, 2026 02:39
@edburns
edburns requested a review from a team as a code owner July 30, 2026 02:39
Copilot AI review requested due to automatic review settings July 30, 2026 02:39

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds Java FFI platform detection and native runtime extraction/caching.

Changes:

  • Detects OS, architecture, and Linux libc classifiers.
  • Resolves and atomically caches runtime.node.
  • Adds Maven-filtered version metadata and unit-test fixtures.
Show a summary per file
File Description
java/pom.xml Enables version resource filtering.
java/src/main/resources/copilot-runtime.properties Supplies artifact version metadata.
java/src/main/java/com/github/copilot/ffi/PlatformDetector.java Implements platform classification.
java/src/main/java/com/github/copilot/ffi/NativeRuntimeLoader.java Implements runtime resolution and caching.
java/src/main/java/com/github/copilot/ffi/NativeRuntimeLoaderException.java Defines loader failures.
java/src/test/java/com/github/copilot/ffi/PlatformDetectorTest.java Tests platform detection.
java/src/test/java/com/github/copilot/ffi/NativeRuntimeLoaderTest.java Tests loader behavior.
java/src/test/resources/native/linux-x64/runtime.node Provides a stub native resource.

Review details

Comments suppressed due to low confidence (1)

java/src/main/java/com/github/copilot/ffi/PlatformDetector.java:265

  • These two individually valid 32-bit values are added as an int, so a malformed PT_INTERP can overflow end, bypass the bounds check, and cause ArrayIndexOutOfBoundsException. That unchecked exception escapes detectLinuxLibc() instead of producing UNKNOWN; compute and validate the end offset as a long before casting.
            int start = (int) pOffset;
            int end = start + (int) pFileSize;
            if (end > size) {
  • Files reviewed: 8/8 changed files
  • Comments generated: 7
  • Review effort level: Medium

Comment thread java/src/main/java/com/github/copilot/ffi/NativeRuntimeLoader.java Outdated
Comment thread java/src/test/java/com/github/copilot/ffi/NativeRuntimeLoaderTest.java Outdated
Comment thread java/src/test/java/com/github/copilot/ffi/NativeRuntimeLoaderTest.java Outdated
Comment thread java/src/test/java/com/github/copilot/ffi/NativeRuntimeLoaderTest.java Outdated
Comment thread java/src/test/java/com/github/copilot/ffi/NativeRuntimeLoaderTest.java Outdated
Comment thread java/src/test/java/com/github/copilot/ffi/PlatformDetectorTest.java Outdated
Comment thread java/src/main/java/com/github/copilot/ffi/PlatformDetector.java
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

Cross-SDK Consistency Review ✅

This PR adds PlatformDetector and NativeRuntimeLoader in the com.github.copilot.ffi package — Java-internal infrastructure for locating and extracting the native runtime.node binary at runtime.

No cross-SDK consistency issues found. Here's why:

  • Java-specific concern: Embedding and extracting a platform-specific binary from a JAR is a Java packaging constraint. Other SDKs handle CLI resolution differently by design:
    • Node.js: Uses native Node bindings — no extraction needed
    • Python: Invokes the CLI via subprocess using an environment-resolved path
    • Go: Uses os/exec with COPILOT_CLI_PATH or PATH lookup
    • .NET: Uses Process with environment-resolved path
    • Rust: Uses std::process::Command with environment-resolved path
  • Internal package: The ffi package is not part of the public SDK API surface (CopilotClient, session management, tool registration), so no parallel public API changes are needed in other SDKs.
  • Environment variable parity: The COPILOT_CLI_PATH env var fallback is already the standard cross-SDK mechanism for overriding CLI path — this PR correctly honors it, staying consistent with all other SDKs.

The PR is well-scoped to a Java-specific need and does not introduce any cross-language API inconsistencies.

Generated by SDK Consistency Review Agent for #2157 · sonnet46 17.9 AIC · ⌖ 8.24 AIC · ⊞ 6.6K ·

@edburns

edburns commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

@copilot review

Copilot AI commented Jul 30, 2026

Copy link
Copy Markdown
Contributor Author

@copilot review

Reviewed the current state of the PR. All CI workflows pass on commit 406ae3c. Here's a summary:

Addressed in the previous commit (406ae3c):

  • COPILOT_RUNTIME_PATH is now a dedicated override distinct from COPILOT_CLI_PATH; the CLI path is only used for the sibling fallback (step 3)
  • Tests call production NativeRuntimeLoader.extractToCache(), resolve(), and loadVersion(ClassLoader) directly rather than test-only reimplementations
  • Override precedence verified via NativeRuntimeLoader.resolve(runtimeOverride, ...) with assertions that the explicit path is returned before extraction
  • Isolated classloader injection used for version-loading failure cases
  • PlatformDetectorTest uses parameterized tuple-driven tests with production classifier derivation, including rejection of unsupported OS/arch tuples
  • ELF PT_INTERP parsing validates class-specific minimum program-header entry sizes (≥56 bytes for ELF64, ≥32 bytes for ELF32) using long arithmetic to prevent overflow

No new issues found. Formatting passes (spotless:check). The build requires JDK 25+ per the enforcer rule, which is satisfied in CI.

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.

[Java] Embed Rust CLI runtime 4.3: Native binary extraction and caching

3 participants