Merge "Revert "Revert "Move annotations to native."""
diff --git a/libart/src/main/java/java/lang/Class.java b/libart/src/main/java/java/lang/Class.java
index 7e5cfb7..0dc4bc4 100644
--- a/libart/src/main/java/java/lang/Class.java
+++ b/libart/src/main/java/java/lang/Class.java
@@ -37,6 +37,7 @@
import java.io.InputStream;
import java.io.Serializable;
import java.lang.annotation.Annotation;
+import java.lang.annotation.Inherited;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
@@ -53,7 +54,9 @@
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
import libcore.reflect.AnnotationAccess;
import libcore.reflect.GenericSignatureParser;
@@ -354,7 +357,25 @@
}
@Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
- return AnnotationAccess.getAnnotation(this, annotationType);
+ if (annotationType == null) {
+ throw new NullPointerException("annotationType == null");
+ }
+
+ A annotation = getDeclaredAnnotation(annotationType);
+ if (annotation != null) {
+ return annotation;
+ }
+
+ if (annotationType.isDeclaredAnnotationPresent(Inherited.class)) {
+ for (Class<?> sup = getSuperclass(); sup != null; sup = sup.getSuperclass()) {
+ annotation = sup.getDeclaredAnnotation(annotationType);
+ if (annotation != null) {
+ return annotation;
+ }
+ }
+ }
+
+ return null;
}
/**
@@ -364,7 +385,33 @@
* @see #getDeclaredAnnotations()
*/
@Override public Annotation[] getAnnotations() {
- return AnnotationAccess.getAnnotations(this);
+ /*
+ * We need to get the annotations declared on this class, plus the
+ * annotations from superclasses that have the "@Inherited" annotation
+ * set. We create a temporary map to use while we accumulate the
+ * annotations and convert it to an array at the end.
+ *
+ * It's possible to have duplicates when annotations are inherited.
+ * We use a Map to filter those out.
+ *
+ * HashMap might be overkill here.
+ */
+ HashMap<Class<?>, Annotation> map = new HashMap<Class<?>, Annotation>();
+ for (Annotation declaredAnnotation : getDeclaredAnnotations()) {
+ map.put(declaredAnnotation.annotationType(), declaredAnnotation);
+ }
+ for (Class<?> sup = getSuperclass(); sup != null; sup = sup.getSuperclass()) {
+ for (Annotation declaredAnnotation : sup.getDeclaredAnnotations()) {
+ Class<? extends Annotation> clazz = declaredAnnotation.annotationType();
+ if (!map.containsKey(clazz) && clazz.isDeclaredAnnotationPresent(Inherited.class)) {
+ map.put(clazz, declaredAnnotation);
+ }
+ }
+ }
+
+ /* Convert annotation values from HashMap to array. */
+ Collection<Annotation> coll = map.values();
+ return coll.toArray(new Annotation[coll.size()]);
}
/**
@@ -737,10 +784,17 @@
*
* @see #getAnnotations()
*/
- @Override public Annotation[] getDeclaredAnnotations() {
- List<Annotation> result = AnnotationAccess.getDeclaredAnnotations(this);
- return result.toArray(new Annotation[result.size()]);
- }
+ @Override public native Annotation[] getDeclaredAnnotations();
+
+ /**
+ * Returns the annotation if it exists.
+ */
+ private native <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass);
+
+ /**
+ * Returns true if the annotation exists.
+ */
+ private native boolean isDeclaredAnnotationPresent(Class<? extends Annotation> annotationClass);
/**
* Returns an array containing {@code Class} objects for all classes,
@@ -796,7 +850,7 @@
* method or constructor.
*/
public Class<?> getDeclaringClass() {
- if (AnnotationAccess.isAnonymousClass(this)) {
+ if (isAnonymousClass()) {
return null;
}
return AnnotationAccess.getEnclosingClass(this);
@@ -1223,7 +1277,23 @@
}
@Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
- return AnnotationAccess.isAnnotationPresent(this, annotationType);
+ if (annotationType == null) {
+ throw new NullPointerException("annotationType == null");
+ }
+
+ if (isDeclaredAnnotationPresent(annotationType)) {
+ return true;
+ }
+
+ if (annotationType.isDeclaredAnnotationPresent(Inherited.class)) {
+ for (Class<?> sup = getSuperclass(); sup != null; sup = sup.getSuperclass()) {
+ if (sup.isDeclaredAnnotationPresent(annotationType)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
}
/**
diff --git a/libart/src/main/java/java/lang/reflect/Constructor.java b/libart/src/main/java/java/lang/reflect/Constructor.java
index 9711ef4..0dadd8d 100644
--- a/libart/src/main/java/java/lang/reflect/Constructor.java
+++ b/libart/src/main/java/java/lang/reflect/Constructor.java
@@ -36,7 +36,6 @@
import java.lang.annotation.Annotation;
import java.util.Comparator;
import java.util.List;
-import libcore.reflect.AnnotationAccess;
import libcore.reflect.Types;
/**
@@ -97,10 +96,7 @@
* this constructor has no declared exceptions, an empty array will be
* returned.
*/
- public Class<?>[] getExceptionTypes() {
- // TODO: use dex cache to speed looking up class
- return AnnotationAccess.getExceptions(this);
- }
+ public native Class<?>[] getExceptionTypes();
/**
* Returns an array of the {@code Class} objects associated with the
@@ -181,24 +177,23 @@
return super.getGenericExceptionTypes();
}
- @Override public Annotation[] getDeclaredAnnotations() {
- List<Annotation> result = AnnotationAccess.getDeclaredAnnotations(this);
- return result.toArray(new Annotation[result.size()]);
- }
+ @Override public native Annotation[] getDeclaredAnnotations();
@Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
if (annotationType == null) {
throw new NullPointerException("annotationType == null");
}
- return AnnotationAccess.isDeclaredAnnotationPresent(this, annotationType);
+ return isAnnotationPresentNative(annotationType);
}
+ private native boolean isAnnotationPresentNative(Class<? extends Annotation> annotationType);
@Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
if (annotationType == null) {
throw new NullPointerException("annotationType == null");
}
- return AnnotationAccess.getDeclaredAnnotation(this, annotationType);
+ return getAnnotationNative(annotationType);
}
+ private native <A extends Annotation> A getAnnotationNative(Class<A> annotationType);
/**
* Returns an array of arrays that represent the annotations of the formal
@@ -209,9 +204,13 @@
* @return an array of arrays of {@code Annotation} instances
*/
public Annotation[][] getParameterAnnotations() {
- return AnnotationAccess.getParameterAnnotations(
- declaringClassOfOverriddenMethod, dexMethodIndex);
+ Annotation[][] parameterAnnotations = getParameterAnnotationsNative();
+ if (parameterAnnotations == null) {
+ parameterAnnotations = new Annotation[getParameterTypes().length][0];
+ }
+ return parameterAnnotations;
}
+ private native Annotation[][] getParameterAnnotationsNative();
/**
* Returns the constructor's signature in non-printable form. This is called
diff --git a/libart/src/main/java/java/lang/reflect/Field.java b/libart/src/main/java/java/lang/reflect/Field.java
index 37f2ad0..06cc0b2 100644
--- a/libart/src/main/java/java/lang/reflect/Field.java
+++ b/libart/src/main/java/java/lang/reflect/Field.java
@@ -36,7 +36,6 @@
import java.lang.annotation.Annotation;
import java.util.Comparator;
import java.util.List;
-import libcore.reflect.AnnotationAccess;
import libcore.reflect.GenericSignatureParser;
import libcore.reflect.Types;
@@ -218,7 +217,7 @@
* instantiated for some reason
*/
public Type getGenericType() {
- String signatureAttribute = AnnotationAccess.getSignature(this);
+ String signatureAttribute = getSignatureAttribute();
Class<?> declaringClass = getDeclaringClass();
ClassLoader cl = declaringClass.getClassLoader();
GenericSignatureParser parser = new GenericSignatureParser(cl);
@@ -230,6 +229,19 @@
return genericType;
}
+ private String getSignatureAttribute() {
+ String[] annotation = getSignatureAnnotation();
+ if (annotation == null) {
+ return null;
+ }
+ StringBuilder result = new StringBuilder();
+ for (String s : annotation) {
+ result.append(s);
+ }
+ return result.toString();
+ }
+ private native String[] getSignatureAnnotation();
+
/**
* Returns the constructor's signature in non-printable form. This is called
* (only) from IO native code and needed for deriving the serialVersionUID
@@ -240,24 +252,23 @@
return Types.getSignature(getType());
}
- @Override public Annotation[] getDeclaredAnnotations() {
- List<Annotation> result = AnnotationAccess.getDeclaredAnnotations(this);
- return result.toArray(new Annotation[result.size()]);
- }
+ @Override public native Annotation[] getDeclaredAnnotations();
@Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
if (annotationType == null) {
throw new NullPointerException("annotationType == null");
}
- return AnnotationAccess.getDeclaredAnnotation(this, annotationType);
+ return getAnnotationNative(annotationType);
}
+ private native <A extends Annotation> A getAnnotationNative(Class<A> annotationType);
@Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
if (annotationType == null) {
throw new NullPointerException("annotationType == null");
}
- return AnnotationAccess.isDeclaredAnnotationPresent(this, annotationType);
+ return isAnnotationPresentNative(annotationType);
}
+ private native boolean isAnnotationPresentNative(Class<? extends Annotation> annotationType);
/**
* Returns the value of the field in the specified object. This reproduces
diff --git a/libart/src/main/java/java/lang/reflect/Method.java b/libart/src/main/java/java/lang/reflect/Method.java
index a07ec6f..79287ba 100644
--- a/libart/src/main/java/java/lang/reflect/Method.java
+++ b/libart/src/main/java/java/lang/reflect/Method.java
@@ -36,7 +36,6 @@
import java.lang.annotation.Annotation;
import java.util.Comparator;
import java.util.List;
-import libcore.reflect.AnnotationAccess;
import libcore.reflect.Types;
/**
@@ -148,16 +147,7 @@
*
* @return the declared exception classes
*/
- public Class<?>[] getExceptionTypes() {
- if (getDeclaringClass().isProxy()) {
- return getExceptionTypesNative();
- } else {
- // TODO: use dex cache to speed looking up class
- return AnnotationAccess.getExceptions(this);
- }
- }
-
- private native Class<?>[] getExceptionTypesNative();
+ public native Class<?>[] getExceptionTypes();
/**
* Returns an array of {@code Class} objects associated with the parameter
@@ -250,8 +240,9 @@
if (annotationType == null) {
throw new NullPointerException("annotationType == null");
}
- return AnnotationAccess.isDeclaredAnnotationPresent(this, annotationType);
+ return isAnnotationPresentNative(annotationType);
}
+ private native boolean isAnnotationPresentNative(Class<? extends Annotation> annotationType);
/**
* Returns the exception types as an array of {@code Type} instances. If
@@ -288,17 +279,15 @@
return Types.getType(getMethodOrConstructorGenericInfo().genericReturnType);
}
- @Override public Annotation[] getDeclaredAnnotations() {
- List<Annotation> result = AnnotationAccess.getDeclaredAnnotations(this);
- return result.toArray(new Annotation[result.size()]);
- }
+ @Override public native Annotation[] getDeclaredAnnotations();
@Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
if (annotationType == null) {
throw new NullPointerException("annotationType == null");
}
- return AnnotationAccess.getDeclaredAnnotation(this, annotationType);
+ return getAnnotationNative(annotationType);
}
+ private native <A extends Annotation> A getAnnotationNative(Class<A> annotationType);
/**
* Returns an array of arrays that represent the annotations of the formal
@@ -309,9 +298,13 @@
* @return an array of arrays of {@code Annotation} instances
*/
public Annotation[][] getParameterAnnotations() {
- return AnnotationAccess.getParameterAnnotations(
- declaringClassOfOverriddenMethod, dexMethodIndex);
+ Annotation[][] parameterAnnotations = getParameterAnnotationsNative();
+ if (parameterAnnotations == null) {
+ parameterAnnotations = new Annotation[getParameterTypes().length][0];
+ }
+ return parameterAnnotations;
}
+ private native Annotation[][] getParameterAnnotationsNative();
/**
* Returns the default value for the annotation member represented by this
@@ -323,9 +316,7 @@
* if this annotation member is of type {@code Class} and no
* definition can be found
*/
- public Object getDefaultValue() {
- return AnnotationAccess.getDefaultValue(this);
- }
+ public native Object getDefaultValue();
/**
* Returns the result of dynamically invoking this method. Equivalent to