Przemek Bielicki created GROOVY-12431:
-----------------------------------------
Summary: Backport GROOVY-12149 (sorted reflection in
Java8#configureClassNode) to 4.0.x
Key: GROOVY-12431
URL: https://issues.apache.org/jira/browse/GROOVY-12431
Project: Groovy
Issue Type: Bug
Components: Compiler
Affects Versions: 4.0.33
Reporter: Przemek Bielicki
GROOVY-12149 (fixed in 5.0.8 and 6.0.0-beta-1 by
https://github.com/apache/groovy/pull/2690) makes {{Java8#configureClassNode}}
read members in a sorted order instead of {{getDeclaredMethods()}} order. The
4.0.x line still has the unsorted loops: in 4.0.33, {{configureClassNode}}
iterates {{clazz.getDeclaredFields()}}, {{clazz.getDeclaredMethods()}} and
{{clazz.getDeclaredConstructors()}} as returned.
We see non-reproducible output on 4.0.33 in CI that is consistent with this. A
class implements a trait that is compiled in a separate module and consumed as
a jar:
{code:groovy}
// module A, on module B's compile classpath as a jar
trait SharedTrait {
boolean hasFeature() { ... }
String describeFeature(int index = 0) { ... }
}
// module B
class ItemModule extends BaseModule implements SharedTrait {
}
{code}
Gradle compiles the implementing module in a long-lived Groovy compiler daemon.
Across CI agents, identical compile inputs (as Gradle fingerprints them:
sources, compile classpath, Groovy and JDK versions) produce more than one
version of this class: over two days, 13 distinct sets of inputs each produced
at least two different outputs. In the pair we inspected, the only differing
file is this class, the one that weaves in the precompiled trait's methods,
which is the second case described in GROOVY-12149.
This matters for us because the compile task caches by its inputs: builds that
execute it concurrently push different outputs under one cache key, and every
downstream task fingerprinting those classes then misses the build cache.
The PR is small (ReflectionUtils +66, Java8 +3/-7). Could it be backported to
GROOVY_4_0_X for the next 4.0.x release?
A second observation, possibly the same cause but unconfirmed: on 4.0.33 the
anonymous subclasses generated for enum constants with class bodies
({{MyEnum$1}}, {{MyEnum$2}}) also compiled to different bytes across CI agents
under identical inputs. Recompiling that module repeatedly in fresh JVMs
locally, including with randomized identity hash codes, always gave identical
output, which would fit an order that depends on the JVM's class-loading
history. We have not obtained both byte variants yet, so we cannot say whether
the difference is member ordering. We can try to produce them if that would
help.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)