001/* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013package org.jikesrvm.classloader; 014 015import java.io.DataInputStream; 016import java.io.IOException; 017import java.lang.annotation.Annotation; 018 019import org.vmmagic.pragma.Uninterruptible; 020import org.jikesrvm.VM; 021 022/** 023 * A common abstract super class for all elements that can be 024 * annotated within the JVM. Namely classes, methods and fields. 025 */ 026public abstract class AnnotatedElement implements java.lang.reflect.AnnotatedElement { 027 /** 028 * Annotations from the class file that are described as runtime 029 * visible. These annotations are available to the reflection API. 030 * This is either null, a RVMAnnotation if a single annotation is 031 * present, or an array of RVMAnnotation if there is >1 032 */ 033 protected final Object declaredAnnotationDatas; 034 /** Cached array of declared annotations. */ 035 private Annotation[] declaredAnnotations; 036 /** Empty annotation array */ 037 private static final Annotation[] emptyAnnotationArray = new Annotation[0]; 038 039 /** 040 * Constructor used by all annotated elements 041 * 042 * @param annotations array of runtime visible annotations 043 */ 044 protected AnnotatedElement(RVMAnnotation[] annotations) { 045 if (annotations == null) { 046 declaredAnnotationDatas = null; 047 declaredAnnotations = emptyAnnotationArray; 048 } else if (annotations.length == 1) { 049 this.declaredAnnotationDatas = annotations[0]; 050 } else { 051 this.declaredAnnotationDatas = annotations; 052 } 053 if (annotations != null) { 054 for (RVMAnnotation ann : annotations) { 055 if (ann == null) throw new Error("null annotation in " + toString()); 056 } 057 } 058 } 059 060 protected static RVMAnnotation[] readAnnotations(int[] constantPool, DataInputStream input, 061 ClassLoader classLoader) throws IOException { 062 try { 063 int numAnnotations = input.readUnsignedShort(); 064 final RVMAnnotation[] annotations = new RVMAnnotation[numAnnotations]; 065 for (int j = 0; j < numAnnotations; j++) { 066 annotations[j] = RVMAnnotation.readAnnotation(constantPool, input, classLoader); 067 } 068 return annotations; 069 } catch (ClassNotFoundException e) { 070 throw new Error(e); 071 } 072 } 073 074 /** 075 * Get the annotations for this and all super annotated elements. 076 */ 077 @Override 078 public final Annotation[] getAnnotations() { 079 return cloneAnnotations(getAnnotationsInternal()); 080 } 081 082 Annotation[] getAnnotationsInternal() { 083 return getDeclaredAnnotationsInternal(); 084 } 085 086 /** 087 * Get the annotations for this annotated element 088 */ 089 @Override 090 public final Annotation[] getDeclaredAnnotations() { 091 return cloneAnnotations(getDeclaredAnnotationsInternal()); 092 } 093 094 final Annotation[] getDeclaredAnnotationsInternal() { 095 if (!VM.runningVM) { 096 return toAnnotations(declaredAnnotationDatas); 097 } 098 if (null == declaredAnnotations) { 099 declaredAnnotations = toAnnotations(declaredAnnotationDatas); 100 } 101 return declaredAnnotations; 102 } 103 104 private Annotation[] cloneAnnotations(final Annotation[] internal) { 105 if (internal.length == 0) { 106 return emptyAnnotationArray; 107 } else { 108 final Annotation[] annotations = new Annotation[internal.length]; 109 System.arraycopy(internal, 0, annotations, 0, internal.length); 110 return annotations; 111 } 112 } 113 114 /** 115 * Convert annotations from internal format to annotation instances. 116 * 117 * @param datas the annotations. 118 * @return the annotation instances. 119 */ 120 final Annotation[] toAnnotations(final Object datas) { 121 if (null == datas) { 122 return emptyAnnotationArray; 123 } else if (datas instanceof RVMAnnotation) { 124 final Annotation[] copy = new Annotation[1]; 125 copy[0] = ((RVMAnnotation)datas).getValue(); 126 return copy; 127 } else { 128 RVMAnnotation[] annotations = (RVMAnnotation[])datas; 129 final Annotation[] copy = new Annotation[annotations.length]; 130 for (int i = 0; i < copy.length; i++) { 131 copy[i] = annotations[i].getValue(); 132 } 133 return copy; 134 } 135 } 136 137 /** 138 * Get the annotation implementing the specified class or null 139 */ 140 @Override 141 @SuppressWarnings({"unchecked"}) 142 public final <T extends Annotation> T getAnnotation(Class<T> annotationClass) { 143 if (null == annotationClass) { 144 throw new NullPointerException("annotationClass"); 145 } 146 final Annotation[] annotations = getAnnotationsInternal(); 147 for (final Annotation annotation : annotations) { 148 if (annotationClass.isInstance(annotation)) return (T) annotation; 149 } 150 return null; 151 } 152 153 /** 154 * Is there an annotation of this type implemented on this annotated 155 * element? 156 */ 157 @Override 158 public final boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) { 159 return getAnnotation(annotationClass) != null; 160 } 161 162 /** 163 * Checks if an annotation is declared. 164 * <p> 165 * This is provided as an alternative to isAnnotationPresent() as isAnnotationPresent() 166 * may require classloading and instantiation of annotations. Classloading would mean 167 * that it would not be @Uninterruptible. Instantiation is not desirable as checking 168 * of annotations occurs prior to the bootimage compiler being ready to instantiate 169 * objects. 170 * 171 * @param annotationTypeRef the annotation to check for 172 * @return {@code true} if annotation present. 173 */ 174 @Uninterruptible 175 final boolean isAnnotationDeclared(final TypeReference annotationTypeRef) { 176 if (declaredAnnotationDatas == null) { 177 return false; 178 } else if (declaredAnnotationDatas instanceof RVMAnnotation) { 179 RVMAnnotation annotation = (RVMAnnotation)declaredAnnotationDatas; 180 return annotation.annotationType() == annotationTypeRef; 181 } else { 182 for (RVMAnnotation annotation : (RVMAnnotation[])declaredAnnotationDatas) { 183 if (annotation.annotationType() == annotationTypeRef) { 184 return true; 185 } 186 } 187 return false; 188 } 189 } 190 191 /** 192 * @return {@code true} if the element has at least one annotation 193 */ 194 @Uninterruptible 195 public final boolean hasAnnotations() { 196 return declaredAnnotationDatas != null; 197 } 198 199 /** 200 * @return {@code true} if this element has a Interruptible annotation. 201 * @see org.vmmagic.pragma.Interruptible 202 */ 203 public final boolean hasInterruptibleAnnotation() { 204 return isAnnotationDeclared(TypeReference.Interruptible); 205 } 206 207 /** 208 * @return {@code true} if this element has a LogicallyUninterruptible annotation. 209 * @see org.vmmagic.pragma.LogicallyUninterruptible 210 */ 211 public final boolean hasLogicallyUninterruptibleAnnotation() { 212 return isAnnotationDeclared(TypeReference.LogicallyUninterruptible); 213 } 214 215 /** 216 * @return {@code true} if this element has a Preemptible annotation. 217 * @see org.vmmagic.pragma.Preemptible 218 */ 219 public final boolean hasPreemptibleAnnotation() { 220 return isAnnotationDeclared(TypeReference.Preemptible); 221 } 222 223 /** 224 * @return {@code true} if this element has a UninterruptibleNoWarn annotation. 225 * @see org.vmmagic.pragma.UninterruptibleNoWarn 226 */ 227 public final boolean hasUninterruptibleNoWarnAnnotation() { 228 return isAnnotationDeclared(TypeReference.UninterruptibleNoWarn); 229 } 230 231 /** 232 * @return {@code true} if this element has a UninterruptibleNoWarn annotation. 233 * @see org.vmmagic.pragma.UninterruptibleNoWarn 234 */ 235 public final boolean hasUnpreemptibleNoWarnAnnotation() { 236 return isAnnotationDeclared(TypeReference.UnpreemptibleNoWarn); 237 } 238 239 /** 240 * @return {@code true} if this element has a Uninterruptible annotation. 241 * @see org.vmmagic.pragma.Uninterruptible 242 */ 243 public final boolean hasUninterruptibleAnnotation() { 244 return isAnnotationDeclared(TypeReference.Uninterruptible); 245 } 246 /** 247 * @return {@code true} if this element has a NoCheckStore annotation. 248 * @see org.vmmagic.pragma.NoCheckStore 249 */ 250 public final boolean hasNoCheckStoreAnnotation() { 251 return isAnnotationDeclared(TypeReference.NoCheckStore); 252 } 253 254 /** 255 * @return {@code true} if this element has a Unpreemptible annotation. 256 * @see org.vmmagic.pragma.Unpreemptible 257 */ 258 public final boolean hasUnpreemptibleAnnotation() { 259 return isAnnotationDeclared(TypeReference.Unpreemptible); 260 } 261 262 /** 263 * @return {@code true} if this element has a NoOptCompile annotation. 264 * @see org.vmmagic.pragma.NoOptCompile 265 */ 266 public final boolean hasNoOptCompileAnnotation() { 267 return isAnnotationPresent(org.vmmagic.pragma.NoOptCompile.class); 268 } 269 270 /** 271 * @return {@code true} if this element has a Inline annotation. 272 * @see org.vmmagic.pragma.Inline 273 */ 274 public final boolean hasInlineAnnotation() { 275 return isAnnotationPresent(org.vmmagic.pragma.Inline.class); 276 } 277 278 /** 279 * @return {@code true} if this element has a NoInline annotation. 280 * @see org.vmmagic.pragma.NoInline 281 */ 282 public final boolean hasNoInlineAnnotation() { 283 return isAnnotationPresent(org.vmmagic.pragma.NoInline.class); 284 } 285 286 /** 287 * @return {@code true} if this element has a BaselineNoRegisters annotation. 288 * @see org.vmmagic.pragma.BaselineNoRegisters 289 */ 290 public final boolean hasBaselineNoRegistersAnnotation() { 291 return isAnnotationDeclared(TypeReference.BaselineNoRegisters); 292 } 293 294 /** 295 * @return {@code true} if this element has a BaselineSaveLSRegisters annotation. 296 * @see org.vmmagic.pragma.BaselineSaveLSRegisters 297 */ 298 @Uninterruptible 299 public final boolean hasBaselineSaveLSRegistersAnnotation() { 300 return isAnnotationDeclared(TypeReference.BaselineSaveLSRegisters); 301 } 302 303 /** 304 * @return {@code true} if this element has a Pure annotation. 305 * @see org.vmmagic.pragma.Pure 306 */ 307 public final boolean hasPureAnnotation() { 308 return isAnnotationPresent(org.vmmagic.pragma.Pure.class); 309 } 310 311 /** 312 * @return {@code true} if this element has a RuntimePure annotation. 313 * @see org.vmmagic.pragma.RuntimePure 314 */ 315 public final boolean hasRuntimePureAnnotation() { 316 return isAnnotationPresent(org.vmmagic.pragma.RuntimePure.class); 317 } 318 319 /** 320 * @return {@code true} if this element has a NoNullCheck annotation. 321 * @see org.vmmagic.pragma.NoNullCheck 322 */ 323 public final boolean hasNoNullCheckAnnotation() { 324 return isAnnotationPresent(org.vmmagic.pragma.NoNullCheck.class); 325 } 326 327 /** 328 * @return {@code true} if this element has a NoBoundsCheck annotation. 329 * @see org.vmmagic.pragma.NoBoundsCheck 330 */ 331 public final boolean hasNoBoundsCheckAnnotation() { 332 return isAnnotationPresent(org.vmmagic.pragma.NoBoundsCheck.class); 333 } 334 335 /** 336 * @return {@code true} if this element has a RuntimeFinal annotation. 337 * @see org.vmmagic.pragma.RuntimeFinal 338 */ 339 public final boolean hasRuntimeFinalAnnotation() { 340 return isAnnotationPresent(org.vmmagic.pragma.RuntimeFinal.class); 341 } 342 343 /** 344 * @return {@code true} if this element has a NoEscapes annotation. 345 * @see org.vmmagic.pragma.NoEscapes 346 */ 347 public final boolean hasNoEscapesAnnotation() { 348 return isAnnotationPresent(org.vmmagic.pragma.NoEscapes.class); 349 } 350 351 /** 352 * @return {@code true} if this element has a Untraced annotation. 353 * @see org.vmmagic.pragma.Untraced 354 */ 355 @Uninterruptible 356 public final boolean hasUntracedAnnotation() { 357 return isAnnotationDeclared(TypeReference.Untraced); 358 } 359 360 /** 361 * @return {@code true} if this element has a NonMoving annotation. 362 * @see org.vmmagic.pragma.NonMoving 363 */ 364 public final boolean hasNonMovingAnnotation() { 365 return isAnnotationDeclared(TypeReference.NonMoving); 366 } 367 368 /** 369 * @return {@code true} if this element has a NonMovingAllocation annotation. 370 * @see org.vmmagic.pragma.NonMovingAllocation 371 */ 372 public final boolean hasNonMovingAllocationAnnotation() { 373 return isAnnotationDeclared(TypeReference.NonMovingAllocation); 374 } 375}