codeconsole opened a new issue, #16753:
URL: https://github.com/apache/grails-core/issues/16753
To start in a native image without recorded metadata, the framework
registers every Groovy class it scans as a reflection type
(`BytecodeRuntimeHints`, added in #16180: the loop over `isGroovyClass` at the
end of `register`). Its javadoc gives the reason. Before Groovy writes a
property dynamically, it asks `Class.getMethod("setProperty", ...)` whether the
class overrides `setProperty`. An image answers that only for a registered
type. Without the registration, the bean DSL could not set the first bean's
options and failed with `NoSuchMethodException` for a method the class plainly
has.
apache/groovy#3023 removes the need for that registration on both sides of
property access:
- Groovy now caches the `setProperty` and `getProperty` override checks per
class.
- When reflection cannot answer, the write or read goes to the object's own
`setProperty`/`getProperty` instead of throwing, or, for invokedynamic reads,
instead of silently going around it to the metaclass.
A native-image probe in the PR shows every write and read path reaching an
unregistered class's own `setProperty`/`getProperty` with the fix, and throwing
or returning the wrong value without it.
## What to change once a Groovy release with apache/groovy#3023 is in use
- [ ] Remove the every-Groovy-class type registration from
`BytecodeRuntimeHints`: the `isGroovyClass` loop and its counter in the debug
log, `isGroovyClass` itself, and the last bullet of the class javadoc ("A
Groovy object given a property dynamically is first asked, through
`Class.getMethod`, ...").
- [ ] Remove or invert the two features of `BytecodeRuntimeHintsSpec` that
pin it: 'a Groovy class can be asked about its methods' and 'a class that is
not a Groovy class is not registered for that'.
- [ ] Build the native-i18n image and run its checks: `./gradlew
:native-i18n:check -PnativeTests` from `end-to-end`, with a GraalVM `JAVA_HOME`.
## What to watch for
The javadoc says the registration is only there for this check, but
registering a type may be doing more. It also lets the image answer reflective
queries about the class's members, which Groovy makes when it builds a
metaclass for the class. If the native-i18n checks fail without the
registration, do not drop it. Find what still needs it, narrow the registration
to that, and correct the javadoc to the real reason.
The same check exists in the classic call sites of the optional
`groovy-callsite` module, which Grails 9 does not use (it compiles with
invokedynamic). Those call sites already fall back to the object's
`getProperty`.
## Groovy version
apache/groovy#3023 targets Groovy master (7.0.0-SNAPSHOT). Grails 9 builds
with Groovy 6.0.x, so it only benefits once the change is backported to
`GROOVY_6_0_X`; the PR asks for that.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]