You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Paul King (Jira)" <ji...@apache.org> on 2026/09/06 14:45:00 UTC

[jira] [Resolved] (GROOVY-12366) native: add a native-image.properties file

     [ https://issues.apache.org/jira/browse/GROOVY-12366?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Paul King resolved GROOVY-12366.
--------------------------------
    Fix Version/s: 6.0.0-RC-2
         Assignee: Paul King
       Resolution: Fixed

> native: add a native-image.properties file
> ------------------------------------------
>
>                 Key: GROOVY-12366
>                 URL: https://issues.apache.org/jira/browse/GROOVY-12366
>             Project: Groovy
>          Issue Type: Improvement
>            Reporter: Paul King
>            Assignee: Paul King
>            Priority: Major
>             Fix For: 6.0.0-RC-2
>
>
> Companion to GROOVY-12365 (which covers the reflection and resource metadata). GraalVM's {{native-image}} reads a {{native-image.properties}} file from any jar on the class path at {{META-INF/native-image/<groupId>/<artifactId>/native-image.properties}}; its {{Args}} line is appended to the build's command line, and the GraalVM Gradle and Maven plugins honour it too. It is the one place a library can state the build arguments it needs so that users do not have to discover them. Groovy currently ships none, and projects that build native images of dynamic Groovy code end up carrying Groovy's requirements in their own build files, for example:
> {code}
> buildArgs.add('--initialize-at-run-time=org.codehaus.groovy.control.XStreamUtils,groovy.grape.GrapeIvy,org.codehaus.groovy.vmplugin.v8.IndyInterface')
> buildArgs.add('-H:IncludeResources=META-INF/dgminfo')
> buildArgs.add('-H:IncludeResources=META-INF/groovy/.*')
> buildArgs.add('-H:IncludeResources=META-INF/services/.*')
> {code}
> h3. Proposal
> Add {{META-INF/native-image/org.apache.groovy/groovy/native-image.properties}} to the {{groovy}} jar with:
> * {{--initialize-at-run-time}} for the runtime classes that must not be initialised at image build time. Recent GraalVM releases default application classes to run-time initialisation, but the analysis may still simulate an initialiser it can prove side-effect free, and Groovy's own code notes the hazard: {{AotDispatch}} avoids caching its AOT decision in a static precisely because "under native image this class may be initialized at image build time", and {{HiddenClassDefiner.isEnabled()}} only checks for the run-time marker, so a build-time initialisation of {{IndyInterface}} would attempt hidden-class definition inside the image builder. Pinning {{org.codehaus.groovy.vmplugin.v8.IndyInterface}}, {{org.apache.groovy.runtime.indy.AotDispatch}}, {{org.apache.groovy.util.HiddenClassDefiner}} and the other property-reading runtime classes makes the AOT link mode's assumptions explicit instead of relying on the default. Classes that historically needed it ({{XStreamUtils}}, {{GrapeIvy}}) should be reviewed rather than copied blindly, since the Iris README already found the blanket flags unnecessary on GraalVM 25.
> * Nothing for resources once GROOVY-12365 ships {{resource-config.json}}; until then the three {{-H:IncludeResources}} patterns above belong here so the two issues can land independently.
> Things that should *not* go in the file, and why:
> * {{-Djdk.logger.packages=...}}. GROOVY-12354 documents that {{java.util.logging}} caller inference in a native image only works if this property is passed at image build time (it is captured by a build-time static initialiser). The properties file is technically the only place Groovy could set it for everyone, but the property is a single comma-separated value, so a later {{-D}} from another jar or the user's own build replaces it wholesale rather than merging. Setting it from a library would silently break other libraries' lists. Keep it documented as a user choice; at most ship the recommended value as a comment in the file.
> * {{--initialize-at-build-time}} for anything: the Iris README records the failures that causes (runtime state in the image heap, e.g. seeded {{Random}} instances), and AOT link mode expects run-time initialisation.
> * {{-H:ConfigurationFileDirectories}} or application-specific reflection: that is the user's audit, which composes with whatever the jar ships.
> h3. Verification
> Build the existing native-image sample (or the small corpus proposed in GROOVY-12365) with plain {{native-image -cp groovy.jar:app ...}} and no extra arguments, on the GraalVM versions the project claims to support, and assert it links and runs. Also confirm {{--trace-class-initialization=org.codehaus.groovy.vmplugin.v8.IndyInterface}} reports run-time initialisation, which is the observable guarantee this file provides.



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