Skip to content

Commit

Permalink
HV-1939 Work around JDK-8303112
Browse files Browse the repository at this point in the history
  • Loading branch information
yrodiere authored and gsmet committed Jun 16, 2023
1 parent f38c0ee commit 58466ed
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

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

List<JavaBeanParameter> parameters = new ArrayList<>( executable.getParameterCount() );
int parameterCount = executable.getParameterCount();
List<JavaBeanParameter> parameters = new ArrayList<>( parameterCount );

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

Annotation[][] parameterAnnotationsArray = executable.getParameterAnnotations();
Annotation[][] annotationsForJDK8303112 =
recomputeParameterAnnotationsForJDK8303112( parameterArray, parameterAnnotationsArray );

for ( int i = 0; i < parameterArray.length; i++ ) {
parameters.add( new JavaBeanParameter( i, parameterArray[i], parameterTypes[i], annotatedTypes[i] ) );
parameters.add( new JavaBeanParameter( i, parameterArray[i], parameterTypes[i], annotatedTypes[i],
annotationsForJDK8303112 != null ? annotationsForJDK8303112[i] : null ) );
}

return CollectionHelper.toImmutableList( parameters );
}

/**
* This is a workaround for <a href="https://bugs.openjdk.org/browse/JDK-8303112">JDK-8303112</a>.
* @param parameters The result of calling {@link Executable#getParameters()}
* @param parameterAnnotationsArray The result of calling {@link Executable#getParameterAnnotations()}
* @return A fixed version of {@code parameterAnnotationsArray},
* or {@code null} if {@code parameterAnnotationsArray} is fine an unaffected by JDK-8303112.
*/
private static Annotation[][] recomputeParameterAnnotationsForJDK8303112(Parameter[] parameters,
Annotation[][] parameterAnnotationsArray) {
int parameterCount = parameters.length;
if ( parameterAnnotationsArray.length == parameterCount ) {
// Not affected by JDK-8303112
return null;
}

// We're in a situation where parameter.getAnnotation()/parameter.getAnnotations()
// is buggy when there are implicit/synthetic parameters,
// because constructor.getParameterAnnotations() (wrongly) ignores implicit/synthetic parameters
// while parameter.getAnnotations() (rightly) assumes they are present in the array.

Annotation[][] annotationsForJDK8303112;
annotationsForJDK8303112 = new Annotation[parameterCount][];
int nonImplicitNorSyntheticParamIndex = 0;
for ( int i = 0; i < parameterCount; i++ ) {
Parameter parameter = parameters[i];
if ( parameter.isImplicit() || parameter.isSynthetic() ) {
annotationsForJDK8303112[i] = new Annotation[0];
}
else if ( nonImplicitNorSyntheticParamIndex < parameterAnnotationsArray.length ) {
annotationsForJDK8303112[i] =
parameterAnnotationsArray[nonImplicitNorSyntheticParamIndex];
++nonImplicitNorSyntheticParamIndex;
}
else {
// Something is wrong; most likely the class wasn't compiled with -parameters
// and so isImplicit/isSynthetic always return false.
// As a last resort, assume the implicit/synthetic parameters are the first ones.
nonImplicitNorSyntheticParamIndex = parameterCount - parameterAnnotationsArray.length;
Arrays.fill( annotationsForJDK8303112, 0, nonImplicitNorSyntheticParamIndex,
new Annotation[0] );
System.arraycopy( parameterAnnotationsArray, 0, annotationsForJDK8303112,
nonImplicitNorSyntheticParamIndex, parameterAnnotationsArray.length );
return annotationsForJDK8303112;
}
}
return annotationsForJDK8303112;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public class JavaBeanParameter implements JavaBeanAnnotatedElement {

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

private static final Annotation[] EMPTY_PARAMETER_ANNOTATIONS = new Annotation[0];
static final Annotation[] EMPTY_PARAMETER_ANNOTATIONS = new Annotation[0];

private final int index;

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

private final AnnotatedType annotatedType;

JavaBeanParameter(int index, Parameter parameter, Class<?> type, AnnotatedType annotatedType) {
private final Annotation[] annotationsForJDK8303112;

JavaBeanParameter(int index, Parameter parameter, Class<?> type, AnnotatedType annotatedType,
Annotation[] annotationsForJDK8303112) {
this.index = index;
this.parameter = parameter;
this.type = type;
this.genericType = getErasedTypeIfTypeVariable( annotatedType.getType() );
this.annotatedType = annotatedType;
this.annotationsForJDK8303112 = annotationsForJDK8303112;
}

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

@Override
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
if ( annotationsForJDK8303112 != null ) {
// Working around https://bugs.openjdk.org/browse/JDK-8303112
for ( Annotation annotation : annotationsForJDK8303112 ) {
if ( annotationClass.isAssignableFrom( annotation.annotationType() ) ) {
@SuppressWarnings("unchecked")
A castAnnotation = (A) annotation;
return castAnnotation;
}
}
return null;
}
return parameter.getAnnotation( annotationClass );
}

Expand Down

0 comments on commit 58466ed

Please sign in to comment.