GraalVM Reachability Metadata

repository·master·Indexed 19 days ago

https://github.com/oracle/graalvm-reachability-metadata

A central collection of reachability metadata for JVM libraries to ensure compatibility with GraalVM Native Image. The repository includes metadata-forge (v0.1.0), an automation tool for adding new library support, improving coverage, and fixing Java or Native Image runtime failures. It utilizes the grund convention for grounded documentation and provides a CLI for resolving stable citations across the project.

Tokens
119.7K
Snippets
173
Records
355
Agent score
63%

What's inside oracle-graalvm-reachability-metadata

  1. Understand the purpose and scope of Forge

    master

    Forge is an automation system located in the forge/ directory designed to resolve GitHub issues in the oracle/graalvm-reachability-metadata repository. It uses LLM-based agents to generate or repair library tests and GraalVM reachability metadata, aiming to increase library coverage and shorten the time from issue report to shipped metadata.

    Supported Issue-Resolution Queues

    Forge automates the following workflows based on specific GitHub labels:

    1. New library support (library-new-request): Generates a JUnit (or Kotlin/Scala) test suite and produces reachability metadata for previously unsupported libraries.
    2. Coverage improvement (library-update-request): Increases dynamic-access coverage for existing libraries.
    3. Code coverage improvement: A planned workflow that uses GraalVM PGO runtime profiles to broaden ordinary API and execution coverage (distinct from dynamic-access coverage).
    4. Java compilation fixes (fails-javac-compile): Repairs test sources that fail to compile after a library version bump.
    5. Java runtime fixes (fails-java-run): Repairs JVM-mode test failures caused by library version updates.
    6. Native-image runtime fixes (fails-native-image-run): Updates reachability metadata to ensure nativeTest passes against new library versions.

    Note: Forge only handles tasks that result in reachability metadata or supporting tests for the reachability repository.

  2. Overview of repository components

    master

    The repository is composed of several specialized components that manage the lifecycle of metadata:

    ComponentRole
    metadata/The core product containing per-artifact index.json, per-version reachability-metadata.json, the master library list, and schemas.
    tests/ suiteThe test harness and support library used to justify each metadata entry.
    stats/A metrics mirror and Forge run records used for the coverage dashboard.
    Test harness (TCK)A Gradle task surface used to validate, compile, and test coordinates on both the JVM and native-image.
    Build infrastructureA two-layer Gradle build managing the harness, convention plugins, scaffolding, and packaging.
    Infrastructure E2E testsTests (testInfra/testAllInfra) that validate the integrity of the build infrastructure itself.
    CIGitHub Actions workflows that handle PR gating, metadata sweeping, upstream version tracking, and releases.
    ForgeAn automation subproject that converts labeled issues into review-ready Pull Requests.
  3. Check Dynamic-Access Coverage Across Versions

    master

    To ensure quality, compare the dynamic-access coverage between the old and new versions using stats.json files.

    Comparison Rules

    1. Use Percentages Only: Compare dynamicAccess.coverageRatio or the percentage reported in the PR description. You may also compare the dynamicAccess.breakdown for specific types (reflection, resources, proxies, serialization, JNI).
    2. Ignore Absolute Counts: Do not treat changes in absolute coveredCalls or totalCalls as regressions. Only use these numbers to calculate the percentage.
    3. The 20% Rule: A coverage percentage drop of more than 20 percentage points is a blocking issue. A drop of 20 points or less is acceptable.
    4. Do Not Second-Guess: Do not use user-code-filter.json, agent configuration, or metadata contents to argue against the reported stats. Use the values as reported in the stats.json files.

    If stats are missing or stale, request the generateLibraryStats job or relevant CI stats before approving.

  4. Metadata content requirements for GraalVM reachability

    master

    When contributing metadata, you must adhere to these strict formatting and structural rules:

    • Metadata-only bundles: Files must contain only JSON entries for GraalVM's manual-configuration. Build-time tweaks like native-image.properties are forbidden.
    • Conditional registration: Every entry must use a condition with the key typeReached. The older typeReachable is invalid and will be rejected by checkMetadataFiles.
    • Allowed-package conditions: The typeReached condition must reference a class within the artifact's allowed-packages.
    • No test-only entries: Metadata describing types from a test suite must not be shipped. Use splitTestOnlyMetadata to move these to src/test/resources/META-INF/native-image/reachability-metadata.json.
    • Index coverage: Each metadata/<group>/<artifact>/ directory must include a valid index.json enumerating metadata versions and tested library versions.
    • Single latest entry: Exactly one entry in a non-empty index.json must have latest: true.
    {
      "condition": {
        "typeReached": "com.example.MyClass"
      }
    }
  5. Understand the structure of the `metadata/` suite

    master

    The metadata/ directory contains the curated GraalVM reachability metadata that native-build-tools resolves and passes to native-image. The metadata is purely additive: it fills in registrations that native-image would otherwise miss and must never change how a consumer's code runs.

    Directory Layout

    • metadata/<groupId>/<artifactId>/index.json: A JSON array for each supported artifact. It defines how native-build-tools selects a metadata version using fields like tested-versions, allowed-packages, latest, requires, and language.
    • metadata/<groupId>/<artifactId>/<metadata-version>/reachability-metadata.json: The actual file loaded by native-image. It contains reflection, jni, resources, bundles, serialization, and foreignCalls entries in a single-file format. Note: Legacy split-config files (e.g., reflect-config.json) are not used here.
    • metadata/library-and-framework-list.json: The master list of all supported libraries and their test_level.
    • metadata/schemas/: Vendored JSON schemas used for validation.
  6. Understand the two-layer build architecture

    master

    The repository uses a two-layer Gradle build designed for isolation and metadata-driven discovery. This architecture ensures that adding a new library only requires adding metadata, without needing to modify the core build logic.

    1. Harness Layer (Repository Root): Manages the high-level orchestration. It handles coordinate filtering (via -Pcoordinates=), metadata/index validation, reporting, CI matrix generation, and packaging. It resolves coordinates and delegates execution to the per-coordinate layer.
    2. Per-coordinate Layer: Each library has its own isolated Gradle build located at tests/src/<group>/<artifact>/<version>/. These builds apply the org.graalvm.internal.tck plugin and manage specific test lanes (javaTest/nativeTest), JaCoCo coverage, and timeout guards.
  7. Understand the core purpose and consumption model of Reachability Metadata

    master

    The GraalVM Reachability Metadata Repository hosts curated, versioned metadata that describes reflection, JNI, resource access, serialization, and proxy use. This information is required for GraalVM native-image to correctly handle libraries that are not yet self-contained for native compilation.

    How it is consumed

    Application developers do not interact with the metadata directly. Instead, the GraalVM Gradle and Maven plugins automatically download the required metadata from this repository at build time to resolve dependencies for the native image build.

  8. Understand the purpose of the GraalVM Reachability Metadata Repository

    master

    The GraalVM Reachability Metadata Repository provides a shared, curated source of metadata for community JVM libraries. Its primary purpose is to allow application developers to build GraalVM Native Image applications using standard libraries without having to manually write reachability metadata for every dependency.

    It specifically addresses dynamic-access registrations that the native-image tool cannot infer through static analysis, ensuring that the library's behavior remains consistent with its standard JVM execution.

  9. How the test suite is exercised

    master

    The test harness executes each coordinate's project through a specific pipeline of lanes:

    1. compileTestJava
    2. javaTest
    3. nativeTestCompile
    4. nativeTest

    CI runs these lanes across the JDK/OS matrix defined in ci.json and in various native-image modes. A version is only considered supported after passing all required environments, and dynamic-access coverage must not regress between consecutive versions.

  10. Understand priority age debt and age bands

    master

    The repository tracks priority age debt to measure neglected high-value work. This is calculated as the weighted age debt of only the high and priority tiers, excluding normal issues.

    Age Calculation: Unresolved age is the number of complete UTC days between an issue's createdAt value and the report generation.

    Age Bands: Issues are categorized into the following inclusive age bands:

    • fresh: 0–7 days
    • aging: 8–30 days
    • old: 31–90 days
    • stale: 91 days or more

    Attention Queue Order: To ensure high-priority work is addressed first, the attention queue is ordered by:

    1. Priority tier (high > priority > normal)
    2. Oldest first
    3. Issue number
  11. Handle unsupported native-image features in tests

    master

    When a test exercises behavior that fundamentally relies on open-ended dynamic class loading that native-image cannot support (such as loading classes, JARs, or generated bytecode discovered only after build), you must use a specific error handling pattern.

    Acceptable Pattern: Use the NativeImageSupport.isUnsupportedFeatureError(e) catch pattern from org.graalvm.internal.tck.

    Rejected Patterns:

    • Raw native-only skips.
    • Bare catch (Error) blocks.
    • Using the isUnsupportedFeatureError pattern for ordinary reflection, resources, serialization, dynamic proxies, JNI, or missing reachability metadata.
    try {
        // code that triggers unsupported dynamic loading
    } catch (Error e) {
        if (org.graalvm.internal.tck.NativeImageSupport.isUnsupportedFeatureError(e)) {
            // Acceptable way to handle truly unsupported dynamic features
        } else {
            throw e;
        }
    }