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 */ 013 package org.jikesrvm.classloader; 014 015 import java.io.DataInputStream; 016 import java.io.IOException; 017 import java.lang.annotation.Annotation; 018 019 import org.vmmagic.pragma.Uninterruptible; 020 import 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 */ 026 public 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 /** 061 * Read annotations from a class file and package in an array 062 * @param constantPool the constantPool of the RVMClass object 063 * that's being constructed 064 * @param input the DataInputStream to read the method's attributes 065 * from 066 * @return an array of read annotations 067 */ 068 protected static RVMAnnotation[] readAnnotations(int[] constantPool, DataInputStream input, 069 ClassLoader classLoader) throws IOException { 070 try { 071 int numAnnotations = input.readUnsignedShort(); 072 final RVMAnnotation[] annotations = new RVMAnnotation[numAnnotations]; 073 for (int j = 0; j < numAnnotations; j++) { 074 annotations[j] = RVMAnnotation.readAnnotation(constantPool, input, classLoader); 075 } 076 return annotations; 077 } catch (ClassNotFoundException e) { 078 throw new Error(e); 079 } 080 } 081 082 /** 083 * Get the annotations for this and all super annotated elements. 084 */ 085 @Override 086 public final Annotation[] getAnnotations() { 087 return cloneAnnotations(getAnnotationsInternal()); 088 } 089 090 Annotation[] getAnnotationsInternal() { 091 return getDeclaredAnnotationsInternal(); 092 } 093 094 /** 095 * Get the annotations for this annotated element 096 */ 097 @Override 098 public final Annotation[] getDeclaredAnnotations() { 099 return cloneAnnotations(getDeclaredAnnotationsInternal()); 100 } 101 102 final Annotation[] getDeclaredAnnotationsInternal() { 103 if (!VM.runningVM) { 104 return toAnnotations(declaredAnnotationDatas); 105 } 106 if (null == declaredAnnotations) { 107 declaredAnnotations = toAnnotations(declaredAnnotationDatas); 108 } 109 return declaredAnnotations; 110 } 111 112 /** 113 * Copy array of annotations so can be safely returned to user. 114 */ 115 private Annotation[] cloneAnnotations(final Annotation[] internal) { 116 if (internal.length == 0) { 117 return emptyAnnotationArray; 118 } else { 119 final Annotation[] annotations = new Annotation[internal.length]; 120 System.arraycopy(internal, 0, annotations, 0, internal.length); 121 return annotations; 122 } 123 } 124 125 /** 126 * Convert annotations from internal format to annotation instances. 127 * 128 * @param datas the annotations. 129 * @return the annotation instances. 130 */ 131 final Annotation[] toAnnotations(final Object datas) { 132 if (null == datas) { 133 return emptyAnnotationArray; 134 } else if (datas instanceof RVMAnnotation) { 135 final Annotation[] copy = new Annotation[1]; 136 copy[0] = ((RVMAnnotation)datas).getValue(); 137 return copy; 138 } else { 139 RVMAnnotation[] annotations = (RVMAnnotation[])datas; 140 final Annotation[] copy = new Annotation[annotations.length]; 141 for (int i = 0; i < copy.length; i++) { 142 copy[i] = annotations[i].getValue(); 143 } 144 return copy; 145 } 146 } 147 148 /** 149 * Get the annotation implementing the specified class or null 150 */ 151 @Override 152 @SuppressWarnings({"unchecked"}) 153 public final <T extends Annotation> T getAnnotation(Class<T> annotationClass) { 154 if (null == annotationClass) { 155 throw new NullPointerException("annotationClass"); 156 } 157 final Annotation[] annotations = getAnnotationsInternal(); 158 for (final Annotation annotation : annotations) { 159 if (annotationClass.isInstance(annotation)) return (T) annotation; 160 } 161 return null; 162 } 163 164 /** 165 * Is there an annotation of this type implemented on this annotated 166 * element? 167 */ 168 @Override 169 public final boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) { 170 return getAnnotation(annotationClass) != null; 171 } 172 173 /** 174 * Return true if annotation present. 175 * 176 * This is provided as an alternative to isAnnotationPresent() as isAnnotationPresent() 177 * may require classloading and instantiation of annotations. Classloading would mean 178 * that it would not be @Uninterruptible. Instantiation is not desirable as checking 179 * of annotations occurs prior to the bootimage compiler being ready to instantiate 180 * objects. 181 */ 182 @Uninterruptible 183 final boolean isAnnotationDeclared(final TypeReference annotationTypeRef) { 184 if (declaredAnnotationDatas == null) { 185 return false; 186 } else if (declaredAnnotationDatas instanceof RVMAnnotation) { 187 RVMAnnotation annotation = (RVMAnnotation)declaredAnnotationDatas; 188 return annotation.annotationType() == annotationTypeRef; 189 } else { 190 for (RVMAnnotation annotation : (RVMAnnotation[])declaredAnnotationDatas) { 191 if (annotation.annotationType() == annotationTypeRef) { 192 return true; 193 } 194 } 195 return false; 196 } 197 } 198 199 /** 200 * Does the element have any annotations? 201 */ 202 @Uninterruptible 203 public final boolean hasAnnotations() { 204 return declaredAnnotationDatas != null; 205 } 206 207 /** 208 * Return true if this element has a Interruptible annotation. 209 * @see org.vmmagic.pragma.Interruptible 210 */ 211 public final boolean hasInterruptibleAnnotation() { 212 return isAnnotationDeclared(TypeReference.Interruptible); 213 } 214 215 /** 216 * Return true if this element has a LogicallyUninterruptible annotation. 217 * @see org.vmmagic.pragma.LogicallyUninterruptible 218 */ 219 public final boolean hasLogicallyUninterruptibleAnnotation() { 220 return isAnnotationDeclared(TypeReference.LogicallyUninterruptible); 221 } 222 223 /** 224 * Return true if this element has a Preemptible annotation. 225 * @see org.vmmagic.pragma.Preemptible 226 */ 227 public final boolean hasPreemptibleAnnotation() { 228 return isAnnotationDeclared(TypeReference.Preemptible); 229 } 230 231 /** 232 * Return true if this element has a UninterruptibleNoWarn annotation. 233 * @see org.vmmagic.pragma.UninterruptibleNoWarn 234 */ 235 public final boolean hasUninterruptibleNoWarnAnnotation() { 236 return isAnnotationDeclared(TypeReference.UninterruptibleNoWarn); 237 } 238 239 /** 240 * Return true if this element has a UninterruptibleNoWarn annotation. 241 * @see org.vmmagic.pragma.UninterruptibleNoWarn 242 */ 243 public final boolean hasUnpreemptibleNoWarnAnnotation() { 244 return isAnnotationDeclared(TypeReference.UnpreemptibleNoWarn); 245 } 246 247 /** 248 * Return true if this element has a Uninterruptible annotation. 249 * @see org.vmmagic.pragma.Uninterruptible 250 */ 251 public final boolean hasUninterruptibleAnnotation() { 252 return isAnnotationDeclared(TypeReference.Uninterruptible); 253 } 254 /** 255 * Return true if this element has a NoCheckStore annotation. 256 * @see org.vmmagic.pragma.NoCheckStore 257 */ 258 public final boolean hasNoCheckStoreAnnotation() { 259 return isAnnotationDeclared(TypeReference.NoCheckStore); 260 } 261 262 /** 263 * Return true if this element has a Unpreemptible annotation. 264 * @see org.vmmagic.pragma.Unpreemptible 265 */ 266 public final boolean hasUnpreemptibleAnnotation() { 267 return isAnnotationDeclared(TypeReference.Unpreemptible); 268 } 269 270 /** 271 * Return true if this element has a NoOptCompile annotation. 272 * @see org.vmmagic.pragma.NoOptCompile 273 */ 274 public final boolean hasNoOptCompileAnnotation() { 275 return isAnnotationPresent(org.vmmagic.pragma.NoOptCompile.class); 276 } 277 278 /** 279 * Return true if this element has a Inline annotation. 280 * @see org.vmmagic.pragma.Inline 281 */ 282 public final boolean hasInlineAnnotation() { 283 return isAnnotationPresent(org.vmmagic.pragma.Inline.class); 284 } 285 286 /** 287 * Return true if this element has a NoInline annotation. 288 * @see org.vmmagic.pragma.NoInline 289 */ 290 public final boolean hasNoInlineAnnotation() { 291 return isAnnotationPresent(org.vmmagic.pragma.NoInline.class); 292 } 293 294 /** 295 * Return true if this element has a BaselineNoRegisters annotation. 296 * @see org.vmmagic.pragma.BaselineNoRegisters 297 */ 298 public final boolean hasBaselineNoRegistersAnnotation() { 299 return isAnnotationDeclared(TypeReference.BaselineNoRegisters); 300 } 301 302 /** 303 * Return true if this element has a BaselineSaveLSRegisters annotation. 304 * @see org.vmmagic.pragma.BaselineSaveLSRegisters 305 */ 306 @Uninterruptible 307 public final boolean hasBaselineSaveLSRegistersAnnotation() { 308 return isAnnotationDeclared(TypeReference.BaselineSaveLSRegisters); 309 } 310 311 /** 312 * Return true if this element has a Pure annotation. 313 * @see org.vmmagic.pragma.Pure 314 */ 315 public final boolean hasPureAnnotation() { 316 return isAnnotationPresent(org.vmmagic.pragma.Pure.class); 317 } 318 319 /** 320 * Return true if this element has a RuntimePure annotation. 321 * @see org.vmmagic.pragma.RuntimePure 322 */ 323 public final boolean hasRuntimePureAnnotation() { 324 return isAnnotationPresent(org.vmmagic.pragma.RuntimePure.class); 325 } 326 327 /** 328 * Return true if this element has a NoNullCheck annotation. 329 * @see org.vmmagic.pragma.NoNullCheck 330 */ 331 public final boolean hasNoNullCheckAnnotation() { 332 return isAnnotationPresent(org.vmmagic.pragma.NoNullCheck.class); 333 } 334 335 /** 336 * Return true if this element has a NoBoundsCheck annotation. 337 * @see org.vmmagic.pragma.NoBoundsCheck 338 */ 339 public final boolean hasNoBoundsCheckAnnotation() { 340 return isAnnotationPresent(org.vmmagic.pragma.NoBoundsCheck.class); 341 } 342 343 /** 344 * Return true if this element has a RuntimeFinal annotation. 345 * @see org.vmmagic.pragma.RuntimeFinal 346 */ 347 public final boolean hasRuntimeFinalAnnotation() { 348 return isAnnotationPresent(org.vmmagic.pragma.RuntimeFinal.class); 349 } 350 351 /** 352 * Return true if this element has a NoEscapes annotation. 353 * @see org.vmmagic.pragma.NoEscapes 354 */ 355 public final boolean hasNoEscapesAnnotation() { 356 return isAnnotationPresent(org.vmmagic.pragma.NoEscapes.class); 357 } 358 359 /** 360 * Return true if this element has a Untraced annotation. 361 * @see org.vmmagic.pragma.Untraced 362 */ 363 @Uninterruptible 364 public final boolean hasUntracedAnnotation() { 365 return isAnnotationDeclared(TypeReference.Untraced); 366 } 367 368 /** 369 * Return true if this element has a NonMoving annotation. 370 * @see org.vmmagic.pragma.NonMoving 371 */ 372 public final boolean hasNonMovingAnnotation() { 373 return isAnnotationDeclared(TypeReference.NonMoving); 374 } 375 376 /** 377 * Return true if this element has a NonMovingAllocation annotation. 378 * @see org.vmmagic.pragma.NonMovingAllocation 379 */ 380 public final boolean hasNonMovingAllocationAnnotation() { 381 return isAnnotationDeclared(TypeReference.NonMovingAllocation); 382 } 383 }