Copilot commented on code in PR #2690:
URL: https://github.com/apache/groovy/pull/2690#discussion_r3574739160


##########
src/main/java/org/codehaus/groovy/vmplugin/v8/Java8.java:
##########
@@ -403,7 +399,7 @@ public void configureClassNode(final CompileUnit 
compileUnit, final ClassNode cl
                 setAnnotationMetaData(f.getAnnotations(), fn);
                 classNode.addField(fn);
             }
-            Method[] methods = clazz.getDeclaredMethods();
+            Method[] methods = ReflectionUtils.getDeclaredMethodsSorted(clazz);
             for (Method m : methods) {

Review Comment:
   `configureClassNode` now uses sorted reflection results for methods and 
constructors, but fields are still collected via `clazz.getDeclaredFields()` 
(nondeterministic order). If field order feeds into emitted class layout, this 
can still produce byte-different class files across JVM runs, undermining the 
reproducible-build goal described in the PR.



##########
src/main/java/org/codehaus/groovy/reflection/ReflectionUtils.java:
##########
@@ -135,6 +137,70 @@ public static List<Method> getDeclaredMethods(final 
Class<?> type, final String
         return doGetMethods(type, name, parameterTypes, 
Class::getDeclaredMethods);
     }
 
+    /**
+     * Returns the declared methods of a class in a deterministic order.
+     * <p>
+     * {@link Class#getDeclaredMethods()} does not guarantee an order, and
+     * HotSpot's varies between JVM runs. When members of a precompiled class
+     * are enumerated at compile time (annotation members copied to generated
+     * code, trait methods woven into implementing classes, MOP {@code super$}
+     * bridge methods, etc.), that order flows into the generated bytecode, so
+     * a nondeterministic order produces byte-different class files from
+     * identical sources. Callers whose output depends on member order should
+     * use this variant so builds are reproducible.
+     *
+     * @param type the class to introspect
+     * @return the declared methods, sorted by name then signature
+     * @since 5.0.8
+     */
+    public static Method[] getDeclaredMethodsSorted(final Class<?> type) {
+        Method[] methods = type.getDeclaredMethods();
+        Arrays.sort(methods, ReflectionUtils::compareMethods);
+        return methods;
+    }

Review Comment:
   The PR description mentions adding 
`ReflectionUtils#getDeclaredFieldsSorted(Class)` for deterministic field 
ordering, but this class currently only adds sorted variants for methods and 
constructors. Without a field-sorting helper, callers like 
`Java8#configureClassNode` cannot easily make field enumeration deterministic 
too.



-- 
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]

Reply via email to