Skip to content

fix(client): add GraalVM Native Image reachability metadata - #407

Open
katinguengan wants to merge 1 commit into
anthropics:mainfrom
katinguengan:feat/graalvm-agent-metadata-generation
Open

katinguengan wants to merge 1 commit into
anthropics:mainfrom
katinguengan:feat/graalvm-agent-metadata-generation

Conversation

@katinguengan

@katinguengan katinguengan commented Sep 27, 2026 •

Copy link
Copy Markdown

Fixes #406

Summary

anthropic-java-core now ships GraalVM Native Image reachability metadata, so Jackson and Kotlin reflection work in native images without users adding their own hints.

The metadata is generated from the compiled classes every time the jar is built. It doesn't depend on CI, on the publishing workflows, or on what the test suite exercises.

Problem

In a native image, every SDK call fails before a request is sent:

kotlin.reflect.jvm.internal.KotlinReflectionInternalError: Unresolved class: class com.anthropic.models.messages.MessageCreateParams$Body
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Class com.anthropic.core.JsonValue$Deserializer has no default (no arg) constructor

Jackson and Kotlin reflection reach SDK classes reflectively, and native images only allow reflection on classes that are registered ahead of time.

Changes

buildSrc/src/main/kotlin/NativeImageMetadata.kt (new)

A cacheable Gradle task that loads the module's compiled classes and writes META-INF/native-image/com.anthropic/anthropic-java-core/reflect-config.json. It registers what META-INF/proguard/anthropic-java-core.pro already keeps:

  • every class, so Kotlin reflection can load the classes a @Metadata annotation names;
  • the constructors (including Kotlin's synthetic default-argument one), fields and annotated methods of each class with a Jackson annotation; and
  • the no-argument constructor of each class a Jackson annotation refers to (serializers, deserializers, filters).

Each entry only applies when its class is reachable in the image (typeReachable condition), so unused types add nothing to the image.

anthropic-java-core/build.gradle.kts

Registers the task and adds its output to the main resources, so the metada

Validation

All runs used main (2.70.0) plus this change, Oracle GraalVM 25.0.4 on maBoot 4.1.1 / Spring AI 2.0.1 app from #406 without any user-supplied hints.

main This PR
Native image: chat, real API ❌ Unresolved class: …MessageCreateParams$Body ✅
Native image: streaming, real API ❌ JsonValue$Deserializer has no default (no arg) constructor ✅
Native image: tool calling, real API ❌ same ✅
JVM: chat, streaming, tool calling, real API ✅ ✅
:anthropic-java-core:test ✅ 8,082 passed
:anthropic-java-core:testJacksonPublished ✅ 7,423 passed

A standalone SDK app (no Spring) built as a native image showed the same before/after result for chat, streaming and tool calling.

Trade-off: image size

The metadata covers the whole API, so every model class Jackson may create . That makes native images larger:

Most SDK classes are reachable anyway, because the client references every service, so the typeReachable condition only partly offsets this. A smaller metadata set would have to list only the classes a particular test run exercised, which brings back the missing-class failures for everything else.

@katinguengan
katinguengan requested a review from a team as a code owner September 27, 2026 22:50
@katinguengan katinguengan changed the title fix: generate GraalVM reachability metadata from SDK tests during publishing Show more lines fix: generate GraalVM reachability metadata from SDK tests during publishing Sep 28, 2026
Generate reflect-config.json for anthropic-java-core from the compiled classes at build time, so Jackson and Kotlin reflection work in native images.

Fixes anthropics#406
@katinguengan
katinguengan force-pushed the feat/graalvm-agent-metadata-generation branch from a5d112c to bec7a8f Compare October 8, 2026 10:30
@katinguengan katinguengan changed the title fix: generate GraalVM reachability metadata from SDK tests during publishing fix(client): add GraalVM Native Image reachability metadata Oct 8, 2026

This branch has not been deployed

No deployments
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.

[Bug]: Native Image runtime failure due to missing GraalVM reachability metadata

1 participant