[ 
https://issues.apache.org/jira/browse/GROOVY-12365?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18112439#comment-18112439
 ] 

Paul King commented on GROOVY-12365:
------------------------------------

Plan for the "dangling groovy-all" part of this issue, after looking at the 
current state of the GraalVM reachability-metadata repository (2026-09-08).

h3. What is there today

The repository has one Groovy core entry, 
{{metadata/org.apache.groovy/groovy-all/index.json}}, added 2026-06-08 by the 
repository's own Forge automation (PR 
oracle/graalvm-reachability-metadata#8189, closing an auto-filed "Support for 
groovy-all 4.0.24" issue):

{code:json}
[
  {
    "not-for-native-image": true,
    "reason": "The published artifact is a POM-only aggregate with no primary 
JVM class-file jar; Native Image metadata should target the Groovy JVM modules 
it depends on.",
    "replacement": "org.apache.groovy:groovy:4.0.24"
  }
]
{code}

The reason is correct. The replacement is the dangling part: there is no 
{{metadata/org.apache.groovy/groovy}} directory at all, so anyone following the 
pointer finds nothing. The only other Groovy entry is groovy-test-junit5, whose 
metadata file is {{{}}}. The repository also has fifteen open auto-filed issues 
asking for support of {{org.apache.groovy:groovy}} (#2451) and the individual 
modules, all still pointing at 4.0.x versions.

Per the repository's functional spec, native-build-tools loads nothing for a 
not-for-native-image coordinate; the reason and replacement strings are free 
text surfaced to humans (the libraries-and-frameworks page and 
{{check-library-support.sh}}). Nothing validates that a replacement coordinate 
exists, and the AWS SDK BOM entry uses prose for its replacement, which is the 
pattern to copy.

h3. Step 1 (Groovy): finish the jar-embedded metadata

The replacement text can only say "the jar ships it" once that is true. After 
GROOVY-12366 the groovy jar carries {{native-image.properties}} and 
{{resource-config.json}} under 
{{META-INF/native-image/org.apache.groovy/groovy/}}; the reflection part 
described above (bootstrap types, BeanInfo/Customizer probe names, dgm proxies) 
is what remains. Two notes from the repository's rules:

* Use the combined {{reachability-metadata.json}} format with {{typeReached}} 
conditions rather than a legacy {{reflect-config.json}}; that is what the 
repository now requires and what current GraalVM prefers.
* Registering ~2,000 dgm proxy classes is exactly the bloat the repository 
forbids in contributed metadata. It is allowed in the jar, but making 
{{GeneratedMetaMethod$Proxy}} stop resolving proxies by name removes the 
problem entirely and is worth doing first.

h3. Step 2 (reachability-metadata repo): correct the entry

A one-file pull request editing the replacement string, e.g.:

{code:json}
"replacement": "Depend on the class-bearing Groovy modules instead: 
org.apache.groovy:groovy, plus groovy-json, groovy-xml and so on as needed. 
From Groovy 6.0.0 the groovy jar ships its own reachability metadata under 
META-INF/native-image/org.apache.groovy/groovy/, which native-image and 
native-build-tools pick up automatically, so no entry in this repository is 
required."
{code}

Run {{./gradlew check}} in that repository before opening the PR (it enforces 
JSON formatting) and fill in the PR template. The repository's contributing 
guide explicitly prefers jar-embedded metadata over repository entries, so this 
is the outcome they want.

h3. Step 3 (optional): list Groovy as a tested library

The same PR can add an {{org.apache.groovy:groovy}} entry to 
{{metadata/library-and-framework-list.json}} with minimum version 6.0.0, 
{{metadata_locations}} pointing at the jar's {{META-INF/native-image}} path in 
the Groovy GitHub tree, {{tests_locations}} pointing at Groovy's native parity 
tests, and {{test_level}} of {{fully-tested}} once the drift test proposed 
above is in place. The file must be re-sorted with the {{jq}} one-liner in 
their contributing guide.

h3. Step 4: close the loop on the auto-filed issues

Comment on oracle/graalvm-reachability-metadata#2451 ("Support for 
org.apache.groovy:groovy") and its module siblings, stating that Groovy 6 ships 
metadata in the jar and that no repository entry is planned. Their automation 
otherwise keeps those open and may try to generate an entry itself, as it did 
for groovy-all.

h3. Not planned: a full repository entry for org.apache.groovy:groovy

Adding {{metadata/org.apache.groovy/groovy/<version>}} is possible with their 
{{scaffold}}/{{generateMetadata}} tasks and a TCK test modelled on the existing 
groovy-test-junit5 one, but is not worth it. The repository forbids 
{{native-image.properties}}, so the {{--initialize-at-run-time}} arguments 
Groovy needs could only come from the jar anyway, meaning such an entry would 
only work for 6.0.0-RC-2 and later, exactly the versions that no longer need 
it. Groovy 4 and 5 cannot run dynamic code in a native image regardless, since 
AOT link mode (GROOVY-12234) is a Groovy 6 feature.


> native: Ship Groovy's own reachability metadata in the groovy jar
> -----------------------------------------------------------------
>
>                 Key: GROOVY-12365
>                 URL: https://issues.apache.org/jira/browse/GROOVY-12365
>             Project: Groovy
>          Issue Type: Improvement
>            Reporter: Paul King
>            Priority: Major
>
> Groovy 6 dynamic code runs in a GraalVM native image thanks to the AOT link 
> mode (GROOVY-12234), but building the image still requires every user to run 
> the {{native-image-agent}} first, purely to capture the reflection and 
> resource access Groovy's *own* runtime performs. The Iris example README says 
> it plainly: without the recorded metadata the image builds and then fails 
> initialising {{GroovySystem}}. Logging frameworks and most libraries solved 
> this years ago by shipping their reachability metadata inside the jar 
> (log4j-core carries 
> {{META-INF/native-image/org.apache.logging.log4j/log4j-core/reflect-config.json}}
>  and {{resource-config.json}}); {{native-image}} picks such files up 
> automatically from the class path, and the GraalVM Gradle/Maven plugins do 
> too. Groovy ships nothing, and the central [GraalVM reachability-metadata 
> repository|https://github.com/oracle/graalvm-reachability-metadata] has no 
> entry for {{org.apache.groovy:groovy}} either (its {{groovy-all}} entry is 
> marked not-for-native-image and points at a {{groovy}} entry that does not 
> exist), so plugin users get nothing there as well.
> h3. What the agent records for Groovy itself
> Two unrelated dynamic applications (the Iris deep-learning example and a 
> small logging probe, both on GraalVM CE 25.2.4) produce almost the same 
> Groovy-owned set: about 180 reflection entries and a handful of resources.
> * Runtime bootstrap types under {{groovy.lang}}, 
> {{org.codehaus.groovy.runtime}}, {{org.codehaus.groovy.reflection}}, 
> {{org.codehaus.groovy.vmplugin}}: {{GroovySystem}}, 
> {{MetaClassRegistryImpl}}, {{Closure}}, {{GString}}, {{GroovyObjectSupport}}, 
> {{ExpandoMetaClass}}, ranges, {{NullObject}}, the VM plugin, etc.
> * The {{Introspector}} probes the metaclass performs for every class it 
> introspects: {{<Type>BeanInfo}} and {{<Type>Customizer}} lookups for each 
> Groovy runtime type above (these are lookups of classes that do not exist; 
> they still need to be registered so the lookup fails quietly rather than with 
> {{MissingReflectionRegistrationError}}).
> * {{org.codehaus.groovy.runtime.dgm$N}} proxy classes (30 to 32 per 
> application), loaded by name from {{GeneratedMetaMethod$Proxy.createProxy}} 
> when a DGM method is first selected. This set is application dependent: a DGM 
> method not exercised during the agent run fails at run time with 
> {{ClassNotFoundException: org.codehaus.groovy.runtime.dgm$1175}} (seen when a 
> code path was added after the agent run).
> * Resources: {{META-INF/dgminfo}}, 
> {{META-INF/groovy/org.codehaus.groovy.runtime.ExtensionModule}}, 
> {{META-INF/services/org.codehaus.groovy.runtime.ExtensionModule}}, plus a 
> {{.class}} resource lookup ({{groovy/concurrent/AsyncScope.class}}).
> h3. Proposal
> Ship the Groovy-owned part of that metadata in the {{groovy}} jar under 
> {{META-INF/native-image/org.apache.groovy/groovy/}} (and the equivalent for 
> modules that need it, e.g. {{groovy-json}}, {{groovy-xml}}), following the 
> log4j-core layout, so that a dynamic Groovy application builds with plain 
> {{native-image -cp ...}} and no agent step:
> * {{reflect-config.json}} / {{reachability-metadata.json}} with the bootstrap 
> types, the {{BeanInfo}} / {{Customizer}} probe names, and the DGM proxies. 
> For the proxies the safe choice is to register all of them (about 2,000 small 
> classes, all of which are in the jar anyway) rather than a sample, since the 
> used set cannot be known ahead of time; alternatively 
> {{GeneratedMetaMethod$Proxy}} could stop resolving them by name (e.g. a 
> generated switch or a {{MethodHandle}} table), which would remove the entries 
> entirely.
> * {{resource-config.json}} for {{META-INF/dgminfo}}, the extension-module 
> descriptors and the service files.
> * A {{native-image.properties}} with {{Args}} carrying what the README 
> currently asks users to type by hand and what the AOT link mode assumes: 
> {{--initialize-at-run-time=org.codehaus.groovy.vmplugin.v8.IndyInterface}} 
> (and the other runtime classes that must not be initialised at build time). 
> This file is also the one place that can set a build-time system property for 
> everybody, which matters for the JUL caller-location workaround documented 
> under GROOVY-12354 ({{-Djdk.logger.packages=...}} is captured by a build-time 
> static initialiser and ignored at run time).
> The metadata should be generated by the build rather than hand-maintained: 
> run the agent over the existing native-image parity corpus (or a small 
> dedicated script) as part of the performance/native tests, diff against the 
> checked-in files, and fail on drift. Once the jar ships it, an entry in the 
> reachability-metadata repository becomes unnecessary (the repository prefers 
> jar-embedded metadata), but its dangling {{groovy-all}} replacement should be 
> corrected or an {{org.apache.groovy:groovy}} entry added pointing at the 
> shipped files.
> h3. Out of scope
> Caller-location accuracy in native images (GraalVM's visible 
> MethodHandle-interpreter frames) is tracked under GROOVY-12354's 
> documentation and the GraalVM issue; the fatal dynamic call to a 
> {{@CallerSensitive}} method and the failing MOP {{super}} call in native 
> images have their own issues.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to