Skip to content

Commit 9b46909

Browse files
committed
Support reproducible builds.
1 parent 9a1e34e commit 9b46909

File tree

8 files changed

+144
-8
lines changed

8 files changed

+144
-8
lines changed

byte-buddy-dep/src/main/java/net/bytebuddy/description/annotation/AnnotationDescription.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1188,7 +1188,7 @@ public Builder defineEnumerationArray(String property, TypeDescription enumerati
11881188
public <T extends Annotation> Builder defineAnnotationArray(String property, Class<T> annotationType, T... annotation) {
11891189
return defineAnnotationArray(property,
11901190
TypeDescription.ForLoadedType.of(annotationType),
1191-
new AnnotationList.ForLoadedAnnotations(annotation).toArray(new AnnotationDescription[0]));
1191+
new AnnotationList.ForLoadedAnnotations(Arrays.asList(annotation)).toArray(new AnnotationDescription[0]));
11921192
}
11931193

11941194
/**

byte-buddy-dep/src/main/java/net/bytebuddy/description/annotation/AnnotationList.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import net.bytebuddy.description.type.TypeList;
2020
import net.bytebuddy.matcher.ElementMatcher;
2121
import net.bytebuddy.matcher.FilterableList;
22+
import net.bytebuddy.utility.AnnotationComparator;
23+
import net.bytebuddy.utility.GraalImageCode;
2224
import net.bytebuddy.utility.nullability.AlwaysNull;
2325
import net.bytebuddy.utility.nullability.MaybeNull;
2426

@@ -227,7 +229,7 @@ class ForLoadedAnnotations extends AbstractBase {
227229
* @param annotation The represented annotations.
228230
*/
229231
public ForLoadedAnnotations(Annotation... annotation) {
230-
this(Arrays.asList(annotation));
232+
this(Arrays.asList(GraalImageCode.getCurrent().sorted(annotation, AnnotationComparator.INSTANCE)));
231233
}
232234

233235
/**

byte-buddy-dep/src/main/java/net/bytebuddy/description/type/TypeDescription.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,7 @@
3636
import net.bytebuddy.dynamic.TargetType;
3737
import net.bytebuddy.implementation.bytecode.StackSize;
3838
import net.bytebuddy.matcher.ElementMatcher;
39-
import net.bytebuddy.utility.CompoundList;
40-
import net.bytebuddy.utility.FieldComparator;
41-
import net.bytebuddy.utility.GraalImageCode;
42-
import net.bytebuddy.utility.JavaType;
39+
import net.bytebuddy.utility.*;
4340
import net.bytebuddy.utility.dispatcher.JavaDispatcher;
4441
import net.bytebuddy.utility.nullability.AlwaysNull;
4542
import net.bytebuddy.utility.nullability.MaybeNull;
@@ -9028,7 +9025,7 @@ public TypeDescription getEnclosingType() {
90289025
* {@inheritDoc}
90299026
*/
90309027
public TypeList getDeclaredTypes() {
9031-
return new TypeList.ForLoadedTypes(type.getDeclaredClasses());
9028+
return new TypeList.ForLoadedTypes(GraalImageCode.getCurrent().sorted(type.getDeclaredClasses(), TypeComparator.INSTANCE));
90329029
}
90339030

90349031
/**
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright 2014 - Present Rafael Winterhalter
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package net.bytebuddy.utility;
17+
18+
import java.lang.annotation.Annotation;
19+
import java.util.Comparator;
20+
21+
/**
22+
* A comparator for guaranteeing a stable order for declared {@link Annotation}s.
23+
*/
24+
public enum AnnotationComparator implements Comparator<Annotation> {
25+
26+
/**
27+
* The singleton instance.
28+
*/
29+
INSTANCE;
30+
31+
/**
32+
* {@inheritDoc}
33+
*/
34+
public int compare(Annotation left, Annotation right) {
35+
if (left == right) {
36+
return 0;
37+
}
38+
return left.annotationType().getName().compareTo(right.annotationType().getName());
39+
}
40+
}

byte-buddy-dep/src/main/java/net/bytebuddy/utility/GraalImageCode.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,16 @@ public enum GraalImageCode {
5757
*/
5858
NONE(false, false);
5959

60+
/**
61+
* Indicates that member properties and annotations should be sorted when being read.
62+
*/
63+
public static final String REPRODUCIBLE_PROPERTIES = "net.bytebuddy.reproducible";
64+
65+
/**
66+
* Resolves if properties should always be sorted at the cost of some runtime overhead.
67+
*/
68+
private static final boolean SORTED = Boolean.parseBoolean(doPrivileged(new GetSystemPropertyAction(REPRODUCIBLE_PROPERTIES)));
69+
6070
/**
6171
* The current image code or {@code null} if the image code was not yet resolved. The image code must be
6272
* initialized lazily to avoid that it's bound to a value during native compilation.
@@ -102,7 +112,7 @@ public static GraalImageCode getCurrent() {
102112
* @return The supplied array, potentially sorted.
103113
*/
104114
public <T> T[] sorted(T[] value, Comparator<? super T> comparator) {
105-
if (defined) {
115+
if (SORTED || defined) {
106116
Arrays.sort(value, comparator);
107117
}
108118
return value;
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright 2014 - Present Rafael Winterhalter
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package net.bytebuddy.utility;
17+
18+
import java.util.Comparator;
19+
20+
/**
21+
* A comparator for guaranteeing a stable order for declared {@link Class}s.
22+
*/
23+
public enum TypeComparator implements Comparator<Class<?>> {
24+
25+
/**
26+
* The singleton instance.
27+
*/
28+
INSTANCE;
29+
30+
/**
31+
* {@inheritDoc}
32+
*/
33+
public int compare(Class<?> left, Class<?> right) {
34+
if (left == right) {
35+
return 0;
36+
}
37+
return left.getName().compareTo(right.getName());
38+
}
39+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package net.bytebuddy.utility;
2+
3+
import org.junit.Rule;
4+
import org.junit.Test;
5+
import org.mockito.Mock;
6+
import org.mockito.junit.MockitoJUnit;
7+
import org.mockito.junit.MockitoRule;
8+
9+
import java.lang.annotation.Annotation;
10+
11+
import static org.hamcrest.CoreMatchers.is;
12+
import static org.hamcrest.MatcherAssert.assertThat;
13+
import static org.mockito.Mockito.when;
14+
15+
public class AnnotationComparatorTest {
16+
17+
@Rule
18+
public MockitoRule mockitoRule = MockitoJUnit.rule();
19+
20+
@Mock
21+
private Annotation left, right;
22+
23+
@Test
24+
@SuppressWarnings({"unchecked", "rawtypes"})
25+
public void testTypeComparison() {
26+
when(left.annotationType()).thenReturn((Class) Object.class);
27+
when(right.annotationType()).thenReturn((Class) String.class);
28+
assertThat(AnnotationComparator.INSTANCE.compare(left, left) == 0, is(true));
29+
assertThat(AnnotationComparator.INSTANCE.compare(left, right) < 0, is(true));
30+
assertThat(AnnotationComparator.INSTANCE.compare(left, right) > 0, is(true));
31+
}
32+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package net.bytebuddy.utility;
2+
3+
import org.junit.Test;
4+
5+
import static org.hamcrest.CoreMatchers.is;
6+
import static org.hamcrest.MatcherAssert.assertThat;
7+
8+
public class TypeComparatorTest {
9+
10+
@Test
11+
public void testTypeComparison() {
12+
assertThat(TypeComparator.INSTANCE.compare(Object.class, Object.class) == 0, is(true));
13+
assertThat(TypeComparator.INSTANCE.compare(Object.class, String.class) < 0, is(true));
14+
assertThat(TypeComparator.INSTANCE.compare(String.class, Object.class) > 0, is(true));
15+
}
16+
}

0 commit comments

Comments
 (0)