Skip to content

Commit 58466ed

Browse files
yrodieregsmet
authored andcommitted
HV-1939 Work around JDK-8303112
1 parent f38c0ee commit 58466ed

File tree

2 files changed

+79
-5
lines changed

2 files changed

+79
-5
lines changed

engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanExecutable.java

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import java.lang.reflect.Parameter;
1515
import java.lang.reflect.Type;
1616
import java.util.ArrayList;
17+
import java.util.Arrays;
1718
import java.util.Collections;
1819
import java.util.List;
1920

@@ -183,16 +184,70 @@ private static List<JavaBeanParameter> getParameters(Executable executable) {
183184
return Collections.emptyList();
184185
}
185186

186-
List<JavaBeanParameter> parameters = new ArrayList<>( executable.getParameterCount() );
187+
int parameterCount = executable.getParameterCount();
188+
List<JavaBeanParameter> parameters = new ArrayList<>( parameterCount );
187189

188190
Parameter[] parameterArray = executable.getParameters();
189191
Class<?>[] parameterTypes = executable.getParameterTypes();
190192
AnnotatedType[] annotatedTypes = executable.getAnnotatedParameterTypes();
191193

194+
Annotation[][] parameterAnnotationsArray = executable.getParameterAnnotations();
195+
Annotation[][] annotationsForJDK8303112 =
196+
recomputeParameterAnnotationsForJDK8303112( parameterArray, parameterAnnotationsArray );
197+
192198
for ( int i = 0; i < parameterArray.length; i++ ) {
193-
parameters.add( new JavaBeanParameter( i, parameterArray[i], parameterTypes[i], annotatedTypes[i] ) );
199+
parameters.add( new JavaBeanParameter( i, parameterArray[i], parameterTypes[i], annotatedTypes[i],
200+
annotationsForJDK8303112 != null ? annotationsForJDK8303112[i] : null ) );
194201
}
195202

196203
return CollectionHelper.toImmutableList( parameters );
197204
}
205+
206+
/**
207+
* This is a workaround for <a href="https://bugs.openjdk.org/browse/JDK-8303112">JDK-8303112</a>.
208+
* @param parameters The result of calling {@link Executable#getParameters()}
209+
* @param parameterAnnotationsArray The result of calling {@link Executable#getParameterAnnotations()}
210+
* @return A fixed version of {@code parameterAnnotationsArray},
211+
* or {@code null} if {@code parameterAnnotationsArray} is fine an unaffected by JDK-8303112.
212+
*/
213+
private static Annotation[][] recomputeParameterAnnotationsForJDK8303112(Parameter[] parameters,
214+
Annotation[][] parameterAnnotationsArray) {
215+
int parameterCount = parameters.length;
216+
if ( parameterAnnotationsArray.length == parameterCount ) {
217+
// Not affected by JDK-8303112
218+
return null;
219+
}
220+
221+
// We're in a situation where parameter.getAnnotation()/parameter.getAnnotations()
222+
// is buggy when there are implicit/synthetic parameters,
223+
// because constructor.getParameterAnnotations() (wrongly) ignores implicit/synthetic parameters
224+
// while parameter.getAnnotations() (rightly) assumes they are present in the array.
225+
226+
Annotation[][] annotationsForJDK8303112;
227+
annotationsForJDK8303112 = new Annotation[parameterCount][];
228+
int nonImplicitNorSyntheticParamIndex = 0;
229+
for ( int i = 0; i < parameterCount; i++ ) {
230+
Parameter parameter = parameters[i];
231+
if ( parameter.isImplicit() || parameter.isSynthetic() ) {
232+
annotationsForJDK8303112[i] = new Annotation[0];
233+
}
234+
else if ( nonImplicitNorSyntheticParamIndex < parameterAnnotationsArray.length ) {
235+
annotationsForJDK8303112[i] =
236+
parameterAnnotationsArray[nonImplicitNorSyntheticParamIndex];
237+
++nonImplicitNorSyntheticParamIndex;
238+
}
239+
else {
240+
// Something is wrong; most likely the class wasn't compiled with -parameters
241+
// and so isImplicit/isSynthetic always return false.
242+
// As a last resort, assume the implicit/synthetic parameters are the first ones.
243+
nonImplicitNorSyntheticParamIndex = parameterCount - parameterAnnotationsArray.length;
244+
Arrays.fill( annotationsForJDK8303112, 0, nonImplicitNorSyntheticParamIndex,
245+
new Annotation[0] );
246+
System.arraycopy( parameterAnnotationsArray, 0, annotationsForJDK8303112,
247+
nonImplicitNorSyntheticParamIndex, parameterAnnotationsArray.length );
248+
return annotationsForJDK8303112;
249+
}
250+
}
251+
return annotationsForJDK8303112;
252+
}
198253
}

engine/src/main/java/org/hibernate/validator/internal/properties/javabean/JavaBeanParameter.java

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public class JavaBeanParameter implements JavaBeanAnnotatedElement {
2626

2727
private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() );
2828

29-
private static final Annotation[] EMPTY_PARAMETER_ANNOTATIONS = new Annotation[0];
29+
static final Annotation[] EMPTY_PARAMETER_ANNOTATIONS = new Annotation[0];
3030

3131
private final int index;
3232

@@ -38,12 +38,16 @@ public class JavaBeanParameter implements JavaBeanAnnotatedElement {
3838

3939
private final AnnotatedType annotatedType;
4040

41-
JavaBeanParameter(int index, Parameter parameter, Class<?> type, AnnotatedType annotatedType) {
41+
private final Annotation[] annotationsForJDK8303112;
42+
43+
JavaBeanParameter(int index, Parameter parameter, Class<?> type, AnnotatedType annotatedType,
44+
Annotation[] annotationsForJDK8303112) {
4245
this.index = index;
4346
this.parameter = parameter;
4447
this.type = type;
4548
this.genericType = getErasedTypeIfTypeVariable( annotatedType.getType() );
4649
this.annotatedType = annotatedType;
50+
this.annotationsForJDK8303112 = annotationsForJDK8303112;
4751
}
4852

4953
public int getIndex() {
@@ -63,10 +67,14 @@ public AnnotatedType getAnnotatedType() {
6367
@Override
6468
public Annotation[] getDeclaredAnnotations() {
6569
try {
70+
if ( annotationsForJDK8303112 != null ) {
71+
// Working around https://bugs.openjdk.org/browse/JDK-8303112
72+
return annotationsForJDK8303112.clone();
73+
}
6674
return parameter.getDeclaredAnnotations();
6775
}
6876
catch (ArrayIndexOutOfBoundsException ex) {
69-
// This looks like a JVM bug we are trying to work around, kept as is for now
77+
// This looks like our workaround failed... assume there were no annotations and hope for the best.
7078
LOG.warn( MESSAGES.constraintOnConstructorOfNonStaticInnerClass(), ex );
7179
return EMPTY_PARAMETER_ANNOTATIONS;
7280
}
@@ -84,6 +92,17 @@ public TypeVariable<?>[] getTypeParameters() {
8492

8593
@Override
8694
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
95+
if ( annotationsForJDK8303112 != null ) {
96+
// Working around https://bugs.openjdk.org/browse/JDK-8303112
97+
for ( Annotation annotation : annotationsForJDK8303112 ) {
98+
if ( annotationClass.isAssignableFrom( annotation.annotationType() ) ) {
99+
@SuppressWarnings("unchecked")
100+
A castAnnotation = (A) annotation;
101+
return castAnnotation;
102+
}
103+
}
104+
return null;
105+
}
87106
return parameter.getAnnotation( annotationClass );
88107
}
89108

0 commit comments

Comments
 (0)