1
1
/*
2
- * Copyright (c) 2023, 2023 , Oracle and/or its affiliates. All rights reserved.
2
+ * Copyright (c) 2023, 2025 , Oracle and/or its affiliates. All rights reserved.
3
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
4
*
5
5
* This code is free software; you can redistribute it and/or modify it
24
24
*/
25
25
package com .oracle .svm .hosted .ameta ;
26
26
27
+ import java .lang .annotation .Annotation ;
27
28
import java .lang .reflect .Field ;
28
29
import java .util .ArrayList ;
29
30
import java .util .Arrays ;
56
57
import com .oracle .svm .hosted .substitute .AnnotationSubstitutionProcessor ;
57
58
import com .oracle .svm .hosted .substitute .AutomaticUnsafeTransformationSupport ;
58
59
import com .oracle .svm .hosted .substitute .FieldValueTransformation ;
60
+ import com .oracle .svm .util .ClassUtil ;
59
61
import com .oracle .svm .util .ReflectionUtil ;
60
62
61
63
import jdk .graal .compiler .nodes .ValueNode ;
@@ -376,13 +378,15 @@ private static JavaConstant interceptWordField(AnalysisField field, JavaConstant
376
378
private static FieldValueComputer createFieldValueComputer (AnalysisField field ) {
377
379
UnknownObjectField unknownObjectField = field .getAnnotation (UnknownObjectField .class );
378
380
if (unknownObjectField != null ) {
381
+ checkMisplacedAnnotation (field .getStorageKind ().isObject (), field );
379
382
return new FieldValueComputer (
380
383
ReflectionUtil .newInstance (unknownObjectField .availability ()),
381
384
extractAnnotationTypes (field , unknownObjectField .types (), unknownObjectField .fullyQualifiedTypes ()),
382
385
unknownObjectField .canBeNull ());
383
386
}
384
387
UnknownPrimitiveField unknownPrimitiveField = field .getAnnotation (UnknownPrimitiveField .class );
385
388
if (unknownPrimitiveField != null ) {
389
+ checkMisplacedAnnotation (field .getStorageKind ().isPrimitive (), field );
386
390
return new FieldValueComputer (
387
391
ReflectionUtil .newInstance (unknownPrimitiveField .availability ()),
388
392
List .of (field .getType ().getJavaClass ()),
@@ -391,6 +395,31 @@ private static FieldValueComputer createFieldValueComputer(AnalysisField field)
391
395
return null ;
392
396
}
393
397
398
+ /**
399
+ * For compatibility reasons, we cannot unify {@link UnknownObjectField} and
400
+ * {@link UnknownPrimitiveField} into a single annotation, but we can at least notify the
401
+ * developers if the annotation is misplaced, e.g. {@link UnknownObjectField} is used on a
402
+ * primitive field and vice versa.
403
+ */
404
+ private static void checkMisplacedAnnotation (boolean condition , AnalysisField field ) {
405
+ if (!condition ) {
406
+ String fieldType ;
407
+ Class <? extends Annotation > expectedAnnotationType ;
408
+ Class <? extends Annotation > usedAnnotationType ;
409
+ if (field .getStorageKind ().isObject ()) {
410
+ fieldType = "object" ;
411
+ expectedAnnotationType = UnknownObjectField .class ;
412
+ usedAnnotationType = UnknownPrimitiveField .class ;
413
+ } else {
414
+ fieldType = "primitive" ;
415
+ expectedAnnotationType = UnknownPrimitiveField .class ;
416
+ usedAnnotationType = UnknownObjectField .class ;
417
+ }
418
+ throw UserError .abort ("@%s should not be used on %s fields, use @%s on %s instead." , ClassUtil .getUnqualifiedName (usedAnnotationType ),
419
+ fieldType , ClassUtil .getUnqualifiedName (expectedAnnotationType ), field .format ("%H.%n" ));
420
+ }
421
+ }
422
+
394
423
private static List <Class <?>> extractAnnotationTypes (AnalysisField field , Class <?>[] types , String [] fullyQualifiedTypes ) {
395
424
List <Class <?>> annotationTypes = new ArrayList <>(Arrays .asList (types ));
396
425
for (String annotationTypeName : fullyQualifiedTypes ) {
0 commit comments