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)

Reply via email to