Refactor ART java.lang.reflect implementation
Bug: 10014286.
(cherry picked from commit 1222a700a25956b0e3634731160017f0d3aa0585)
Change-Id: Ic5672489f6c028d47e6c2a499d6a2bbdd5cc4e4c
diff --git a/libart/src/main/java/java/lang/Class.java b/libart/src/main/java/java/lang/Class.java
index 0d0b64d..cb504ca 100644
--- a/libart/src/main/java/java/lang/Class.java
+++ b/libart/src/main/java/java/lang/Class.java
@@ -40,6 +40,8 @@
import java.lang.reflect.AbstractMethod;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.ArtField;
+import java.lang.reflect.ArtMethod;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.GenericDeclaration;
@@ -135,7 +137,7 @@
private transient DexCache dexCache;
/** static, private, and <init> methods. */
- private transient AbstractMethod[] directMethods;
+ private transient ArtMethod[] directMethods;
/**
* Instance fields. These describe the layout of the contents of an Object. Note that only the
@@ -145,7 +147,7 @@
* All instance fields that refer to objects are guaranteed to be at the beginning of the field
* list. {@link Class#numReferenceInstanceFields} specifies the number of reference fields.
*/
- private transient Field[] iFields;
+ private transient ArtField[] iFields;
/**
* The interface table (iftable_) contains pairs of a interface class and an array of the
@@ -167,7 +169,7 @@
private transient String name;
/** Static fields */
- private transient Field[] sFields;
+ private transient ArtField[] sFields;
/** The superclass, or NULL if this is java.lang.Object, an interface or primitive type. */
private transient Class<? super T> superClass;
@@ -176,7 +178,7 @@
private transient Class<?> verifyErrorClass;
/** Virtual methods defined in this class; invoked through vtable. */
- private transient Method[] virtualMethods;
+ private transient ArtMethod[] virtualMethods;
/**
* Virtual method table (vtable), for use by "invoke-virtual". The vtable from the superclass
@@ -184,7 +186,7 @@
* appended. For abstract classes, methods may be created in the vtable that aren't in
* virtual_ methods_ for miranda methods.
*/
- private transient Method[] vtable;
+ private transient ArtMethod[] vtable;
/** access flags; low 16 bits are defined by VM spec */
private transient int accessFlags;
@@ -235,10 +237,11 @@
}
/**
- * Returns a {@code Class} object which represents the class with the
- * given name. The name should be the name of a non-primitive class, as described in
- * the {@link Class class definition}.
- * Primitive types can not be found using this method; use {@code int.class} or {@code Integer.TYPE} instead.
+ * Returns a {@code Class} object which represents the class with
+ * the given name. The name should be the name of a non-primitive
+ * class, as described in the {@link Class class definition}.
+ * Primitive types can not be found using this method; use {@code
+ * int.class} or {@code Integer.TYPE} instead.
*
* <p>If the class has not yet been loaded, it is loaded and initialized
* first. This is done through either the class loader of the calling class
@@ -258,10 +261,11 @@
}
/**
- * Returns a {@code Class} object which represents the class with the
- * given name. The name should be the name of a non-primitive class, as described in
- * the {@link Class class definition}.
- * Primitive types can not be found using this method; use {@code int.class} or {@code Integer.TYPE} instead.
+ * Returns a {@code Class} object which represents the class with
+ * the given name. The name should be the name of a non-primitive
+ * class, as described in the {@link Class class definition}.
+ * Primitive types can not be found using this method; use {@code
+ * int.class} or {@code Integer.TYPE} instead.
*
* <p>If the class has not yet been loaded, it is loaded first, using the given class loader.
* If the class has not yet been initialized and {@code shouldInitialize} is true,
@@ -304,11 +308,12 @@
ClassLoader classLoader) throws ClassNotFoundException;
/**
- * Returns an array containing {@code Class} objects for all public classes,
- * interfaces, enums and annotations that are members of this class and its
- * superclasses. This does not include classes of implemented interfaces.
- * If there are no such class members or if this object represents a primitive type then an array
- * of length 0 is returned.
+ * Returns an array containing {@code Class} objects for all
+ * public classes, interfaces, enums and annotations that are
+ * members of this class and its superclasses. This does not
+ * include classes of implemented interfaces. If there are no
+ * such class members or if this object represents a primitive
+ * type then an array of length 0 is returned.
*/
public Class<?>[] getClasses() {
List<Class<?>> result = new ArrayList<Class<?>>();
@@ -519,10 +524,19 @@
*/
private Constructor<T> getDeclaredConstructorInternal(Class<?>[] args) {
if (directMethods != null) {
- for (AbstractMethod m : directMethods) {
- if (m instanceof Constructor && m.equalParameters(args)) {
- return (Constructor<T>) m;
+ for (ArtMethod m : directMethods) {
+ int modifiers = m.getAccessFlags();
+ if (Modifier.isStatic(modifiers)) {
+ // skip <clinit> which is a static constructor
+ continue;
}
+ if (!Modifier.isConstructor(modifiers)) {
+ continue;
+ }
+ if (!ArtMethod.equalConstructorParameters(m, args)) {
+ continue;
+ }
+ return new Constructor<T>(m);
}
}
return null;
@@ -558,11 +572,15 @@
private void getDeclaredConstructors(boolean publicOnly, List<Constructor<T>> constructors) {
if (directMethods != null) {
- for (AbstractMethod m : directMethods) {
+ for (ArtMethod m : directMethods) {
int modifiers = m.getAccessFlags();
if (!publicOnly || Modifier.isPublic(modifiers)) {
- if (m instanceof Constructor) {
- constructors.add((Constructor<T>) m);
+ if (Modifier.isStatic(modifiers)) {
+ // skip <clinit> which is a static constructor
+ continue;
+ }
+ if (Modifier.isConstructor(modifiers)) {
+ constructors.add(new Constructor<T>(m));
}
}
}
@@ -668,38 +686,53 @@
// escalated visibility. We never return miranda methods that
// were synthesized by the VM.
int skipModifiers = Modifier.MIRANDA | Modifier.SYNTHETIC;
- Method result = null;
+ ArtMethod artMethodResult = null;
if (virtualMethods != null) {
- for (Method m : virtualMethods) {
- if (name.equals(m.getName()) && m.equalParameters(args)) {
- int modifiers = m.getAccessFlags();
- if ((modifiers & skipModifiers) == 0) {
- return m;
- } else if ((modifiers & Modifier.MIRANDA) == 0) {
- // Remember as potential result if it's not a miranda method.
- result = m;
- }
+ for (ArtMethod m : virtualMethods) {
+ String methodName = ArtMethod.getMethodName(m);
+ if (!name.equals(methodName)) {
+ continue;
+ }
+ if (!ArtMethod.equalMethodParameters(m, args)) {
+ continue;
+ }
+ int modifiers = m.getAccessFlags();
+ if ((modifiers & skipModifiers) == 0) {
+ return new Method(m);
+ }
+ if ((modifiers & Modifier.MIRANDA) == 0) {
+ // Remember as potential result if it's not a miranda method.
+ artMethodResult = m;
}
}
}
- if (result == null) {
+ if (artMethodResult == null) {
if (directMethods != null) {
- for (AbstractMethod m : directMethods) {
- if (m instanceof Method && name.equals(m.getName()) &&
- m.equalParameters(args)) {
- int modifiers = m.getAccessFlags();
- if ((modifiers & skipModifiers) == 0) {
- return (Method) m;
- } else {
- // Direct methods cannot be miranda methods,
- // so this potential result must be synthetic.
- result = (Method) m;
- }
+ for (ArtMethod m : directMethods) {
+ int modifiers = m.getAccessFlags();
+ if (Modifier.isConstructor(modifiers)) {
+ continue;
}
+ String methodName = ArtMethod.getMethodName(m);
+ if (!name.equals(methodName)) {
+ continue;
+ }
+ if (!ArtMethod.equalMethodParameters(m, args)) {
+ continue;
+ }
+ if ((modifiers & skipModifiers) == 0) {
+ return new Method(m);
+ }
+ // Direct methods cannot be miranda methods,
+ // so this potential result must be synthetic.
+ artMethodResult = m;
}
}
}
- return result;
+ if (artMethodResult == null) {
+ return null;
+ }
+ return new Method(artMethodResult);
}
/**
@@ -731,23 +764,23 @@
*/
private void getDeclaredMethods(boolean publicOnly, List<Method> methods) {
if (virtualMethods != null) {
- for (Method m : virtualMethods) {
+ for (ArtMethod m : virtualMethods) {
int modifiers = m.getAccessFlags();
if (!publicOnly || Modifier.isPublic(modifiers)) {
// Add non-miranda virtual methods.
if ((modifiers & Modifier.MIRANDA) == 0) {
- methods.add((Method) m);
+ methods.add(new Method(m));
}
}
}
}
if (directMethods != null) {
- for (AbstractMethod m : directMethods) {
+ for (ArtMethod m : directMethods) {
int modifiers = m.getAccessFlags();
if (!publicOnly || Modifier.isPublic(modifiers)) {
// Add non-constructor direct/static methods.
- if (m instanceof Method) {
- methods.add((Method) m);
+ if (!Modifier.isConstructor(modifiers)) {
+ methods.add(new Method(m));
}
}
}
@@ -862,16 +895,16 @@
private void getDeclaredFields(boolean publicOnly, List<Field> fields) {
if (iFields != null) {
- for (Field f : iFields) {
- if (!publicOnly || Modifier.isPublic(f.getModifiers())) {
- fields.add(f);
+ for (ArtField f : iFields) {
+ if (!publicOnly || Modifier.isPublic(f.getAccessFlags())) {
+ fields.add(new Field(f));
}
}
}
if (sFields != null) {
- for (Field f : sFields) {
- if (!publicOnly || Modifier.isPublic(f.getModifiers())) {
- fields.add(f);
+ for (ArtField f : sFields) {
+ if (!publicOnly || Modifier.isPublic(f.getAccessFlags())) {
+ fields.add(new Field(f));
}
}
}
@@ -883,16 +916,16 @@
*/
private Field getDeclaredFieldInternal(String name) {
if (iFields != null) {
- for (Field f : iFields) {
+ for (ArtField f : iFields) {
if (f.getName().equals(name)) {
- return f;
+ return new Field(f);
}
}
}
if (sFields != null) {
- for (Field f : sFields) {
+ for (ArtField f : sFields) {
if (f.getName().equals(name)) {
- return f;
+ return new Field(f);
}
}
}
diff --git a/libart/src/main/java/java/lang/DexCache.java b/libart/src/main/java/java/lang/DexCache.java
index d0eba2f..5cb6792 100644
--- a/libart/src/main/java/java/lang/DexCache.java
+++ b/libart/src/main/java/java/lang/DexCache.java
@@ -16,8 +16,8 @@
*/
package java.lang;
-import java.lang.reflect.Field;
-import java.lang.reflect.AbstractMethod;
+import java.lang.reflect.ArtField;
+import java.lang.reflect.ArtMethod;
/**
* A dex cache holds resolved copies of strings, fields, methods, and classes from the dexfile.
@@ -28,8 +28,8 @@
Object[] initializedStaticStorage;
String location;
- Field[] resolvedFields;
- AbstractMethod[] resolvedMethods;
+ ArtField[] resolvedFields;
+ ArtMethod[] resolvedMethods;
Class[] resolvedTypes;
String[] strings;
diff --git a/libart/src/main/java/java/lang/reflect/AbstractMethod.java b/libart/src/main/java/java/lang/reflect/AbstractMethod.java
index 6a4b8e9..cacf057 100644
--- a/libart/src/main/java/java/lang/reflect/AbstractMethod.java
+++ b/libart/src/main/java/java/lang/reflect/AbstractMethod.java
@@ -33,60 +33,26 @@
package java.lang.reflect;
import com.android.dex.Dex;
-import com.android.dex.ProtoId;
-import com.android.dex.TypeList;
-
import java.lang.annotation.Annotation;
-import java.util.Arrays;
-import java.util.Comparator;
import java.util.List;
import libcore.reflect.AnnotationAccess;
import libcore.reflect.GenericSignatureParser;
-import libcore.reflect.InternalNames;
import libcore.reflect.ListOfTypes;
import libcore.reflect.Types;
-import libcore.util.EmptyArray;
/**
* This class represents an abstract method. Abstract methods are either methods or constructors.
* @hide
*/
public abstract class AbstractMethod extends AccessibleObject {
- private static final Comparator<AbstractMethod> ORDER_BY_SIGNATURE = null;
- /** Method's declaring class */
- Class<?> declaringClass;
- /** Method access flags (modifiers) */
- private int accessFlags;
- /** DexFile index */
- int methodDexIndex;
- /** Dispatch table entry */
- private int methodIndex;
- /** DexFile offset of CodeItem for this Method */
- private int codeItemOffset;
- /* ART compiler meta-data */
- private int frameSizeInBytes;
- private int coreSpillMask;
- private int fpSpillMask;
- private int mappingTable;
- private int gcMap;
- private int vmapTable;
- /** ART: compiled managed code associated with this Method */
- private int entryPointFromCompiledCode;
- /** ART: entry point from interpreter associated with this Method */
- private int entryPointFromInterpreter;
- /** ART: if this is a native method, the native code that will be invoked */
- private int nativeMethod;
- /* ART: dex cache fast access */
- private String[] dexCacheStrings;
- Class<?>[] dexCacheResolvedTypes;
- AbstractMethod[] dexCacheResolvedMethods;
- private Object[] dexCacheInitializedStaticStorage;
+ protected final ArtMethod artMethod;
- /**
- * Only created by native code.
- */
- AbstractMethod() {
+ protected AbstractMethod(ArtMethod artMethod) {
+ if (artMethod == null) {
+ throw new NullPointerException("artMethod == null");
+ }
+ this.artMethod = artMethod;
}
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
@@ -116,41 +82,33 @@
}
int getModifiers() {
- return fixMethodFlags(accessFlags);
+ return fixMethodFlags(artMethod.getAccessFlags());
}
boolean isVarArgs() {
- return (accessFlags & Modifier.VARARGS) != 0;
+ return (artMethod.getAccessFlags() & Modifier.VARARGS) != 0;
}
boolean isBridge() {
- return (accessFlags & Modifier.BRIDGE) != 0;
+ return (artMethod.getAccessFlags() & Modifier.BRIDGE) != 0;
}
- public boolean isSynthetic() {
- return (accessFlags & Modifier.SYNTHETIC) != 0;
+ boolean isSynthetic() {
+ return (artMethod.getAccessFlags() & Modifier.SYNTHETIC) != 0;
}
/**
* @hide
*/
public final int getAccessFlags() {
- return accessFlags;
+ return artMethod.getAccessFlags();
}
/**
- * Returns the name of the method or constructor represented by this
- * instance.
- *
- * @return the name of this method
- */
- public abstract String getName();
-
- /**
* Returns the class that declares this constructor or method.
*/
Class<?> getDeclaringClass() {
- return declaringClass;
+ return artMethod.getDeclaringClass();
}
/**
@@ -159,25 +117,16 @@
* @hide
*/
public final int getDexMethodIndex() {
- return methodDexIndex;
+ return artMethod.getDexMethodIndex();
}
/**
- * Returns the exception types as an array of {@code Class} instances. If
- * this method has no declared exceptions, an empty array is returned.
+ * Returns the name of the method or constructor represented by this
+ * instance.
*
- * @return the declared exception classes
+ * @return the name of this method
*/
- protected Class<?>[] getExceptionTypes() {
- if (declaringClass.isProxy()) {
- return getExceptionTypesNative();
- } else {
- // TODO: use dex cache to speed looking up class
- return AnnotationAccess.getExceptions(this);
- }
- }
-
- private native Class<?>[] getExceptionTypesNative();
+ abstract public String getName();
/**
* Returns an array of {@code Class} objects associated with the parameter types of this
@@ -187,36 +136,7 @@
* @return the parameter types
*/
public Class<?>[] getParameterTypes() {
- Dex dex = declaringClass.getDex();
- short[] types = dex.parameterTypeIndicesFromMethodIndex(methodDexIndex);
- if (types.length == 0) {
- return EmptyArray.CLASS;
- }
- Class<?>[] parametersArray = new Class[types.length];
- for (int i = 0; i < types.length; i++) {
- // Note, in the case of a Proxy the dex cache types are equal.
- parametersArray[i] = getDexCacheType(dex, types[i] & 0xFFFF);
- }
- return parametersArray;
- }
-
- /**
- * Returns true if the given parameters match those of the method in the given order.
- *
- * @hide
- */
- public boolean equalParameters(Class<?>[] params) {
- Dex dex = getDeclaringClass().getDex();
- short[] types = dex.parameterTypeIndicesFromMethodIndex(methodDexIndex);
- if (types.length != params.length) {
- return false;
- }
- for (int i = 0; i < types.length; i++) {
- if (getDexCacheType(dex, types[i] & 0xFFFF) != params[i]) {
- return false;
- }
- }
- return true;
+ return artMethod.getParameterTypes();
}
/**
@@ -224,7 +144,11 @@
* parameters and return type as this method.
*/
@Override public boolean equals(Object other) {
- return this == other; // exactly one instance of each member in this runtime
+ if (!(other instanceof AbstractMethod)) {
+ return false;
+ }
+ // exactly one instance of each member in this runtime
+ return this.artMethod == ((AbstractMethod) other).artMethod;
}
String toGenericString() {
@@ -275,36 +199,6 @@
@SuppressWarnings("unused")
abstract String getSignature();
- /**
- * Returns a string from the dex cache, computing the string from the dex file if necessary.
- * Note this method replicates {@link java.lang.Class#getDexCacheString(Dex, int)}, but in
- * Method we can avoid one indirection.
- */
- final String getDexCacheString(Dex dex, int dexStringIndex) {
- String s = (String) dexCacheStrings[dexStringIndex];
- if (s == null) {
- s = dex.strings().get(dexStringIndex);
- dexCacheStrings[dexStringIndex] = s;
- }
- return s;
- }
-
- /**
- * Returns a resolved type from the dex cache, computing the string from the dex file if
- * necessary. Note this method replicates {@link java.lang.Class#getDexCacheType(Dex, int)},
- * but in Method we can avoid one indirection.
- */
- final Class<?> getDexCacheType(Dex dex, int dexTypeIndex) {
- Class<?> resolvedType = dexCacheResolvedTypes[dexTypeIndex];
- if (resolvedType == null) {
- int descriptorIndex = dex.typeIds().get(dexTypeIndex);
- String descriptor = getDexCacheString(dex, descriptorIndex);
- resolvedType = InternalNames.getClass(declaringClass.getClassLoader(), descriptor);
- dexCacheResolvedTypes[dexTypeIndex] = resolvedType;
- }
- return resolvedType;
- }
-
static final class GenericInfo {
final ListOfTypes genericExceptionTypes;
final ListOfTypes genericParameterTypes;
@@ -323,7 +217,7 @@
/**
* Returns generic information associated with this method/constructor member.
*/
- GenericInfo getMethodOrConstructorGenericInfo() {
+ final GenericInfo getMethodOrConstructorGenericInfo() {
String signatureAttribute = AnnotationAccess.getSignature(this);
Member member;
Class<?>[] exceptionTypes;
@@ -342,7 +236,9 @@
if (method) {
parser.parseForMethod((GenericDeclaration) this, signatureAttribute, exceptionTypes);
} else {
- parser.parseForConstructor((GenericDeclaration) this, signatureAttribute, exceptionTypes);
+ parser.parseForConstructor((GenericDeclaration) this,
+ signatureAttribute,
+ exceptionTypes);
}
return new GenericInfo(parser.exceptionTypes, parser.parameterTypes,
parser.returnType, parser.formalTypeParameters);
@@ -351,7 +247,7 @@
/**
* Helper for Method and Constructor for toGenericString
*/
- String toGenericStringHelper() {
+ final String toGenericStringHelper() {
StringBuilder sb = new StringBuilder(80);
GenericInfo info = getMethodOrConstructorGenericInfo();
int modifiers = ((Member)this).getModifiers();
@@ -395,5 +291,4 @@
}
return sb.toString();
}
-
}
diff --git a/libart/src/main/java/java/lang/reflect/AccessibleObject.java b/libart/src/main/java/java/lang/reflect/AccessibleObject.java
index f626c7e..dd57a12 100644
--- a/libart/src/main/java/java/lang/reflect/AccessibleObject.java
+++ b/libart/src/main/java/java/lang/reflect/AccessibleObject.java
@@ -35,29 +35,35 @@
import java.lang.annotation.Annotation;
/**
- * The superclass of fields, constructors and methods. Reflective operations
- * like {@link Field#set} and {@link Method#invoke} will fail with an {@link
- * IllegalAccessException} when the caller doesn't satisfy the target's access
- * modifier (either public, protected, package-private or private) and the
- * <i>accessible</i> flag is false. Prevent the exception by setting the
- * <i>accessible</i> flag to true with {@link #setAccessible(boolean)
- * setAccessible(true)}.
+ * {@code AccessibleObject} is the superclass of all member reflection classes
+ * (Field, Constructor, Method). AccessibleObject provides the ability to toggle
+ * a flag controlling access checks for these objects. By default, accessing a
+ * member (for example, setting a field or invoking a method) checks the
+ * validity of the access (for example, invoking a private method from outside
+ * the defining class is prohibited) and throws IllegalAccessException if the
+ * operation is not permitted. If the accessible flag is set to true, these
+ * checks are omitted. This allows privileged code, such as Java object
+ * serialization, object inspectors, and debuggers to have complete access to
+ * objects.
*
- * <p>On Android releases up to and including Android 4.0 (Ice Cream Sandwich),
- * the <i>accessible</i> flag is false by default. On releases after
- * Android 4.0, the <i>accessible</i> flag is true by default and cannot be set
- * to false.
+ * @see Field
+ * @see Constructor
+ * @see Method
*/
-// STOPSHIP 'After 4.0' is a guess; identify the release in which 'accessible' was true by default
public class AccessibleObject implements AnnotatedElement {
protected AccessibleObject() {
}
/**
+ * If true, object is accessible, bypassing normal access checks
+ */
+ private boolean flag = false;
+
+ /**
* Returns true if this object is accessible without access checks.
*/
public boolean isAccessible() {
- return true; // always!
+ return flag;
}
/**
@@ -65,13 +71,17 @@
* IllegalAccessExceptions}.
*/
public void setAccessible(boolean flag) {
- }
+ this.flag = flag;
+ }
/**
* Attempts to set the accessible flag for all objects in {@code objects}.
* Setting this to true prevents {@code IllegalAccessExceptions}.
*/
public static void setAccessible(AccessibleObject[] objects, boolean flag) {
+ for (AccessibleObject object : objects) {
+ object.flag = flag;
+ }
}
@Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
diff --git a/libart/src/main/java/java/lang/reflect/ArtField.java b/libart/src/main/java/java/lang/reflect/ArtField.java
new file mode 100644
index 0000000..6fdcdb2
--- /dev/null
+++ b/libart/src/main/java/java/lang/reflect/ArtField.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.lang.reflect;
+
+import com.android.dex.Dex;
+
+/**
+ * @hide
+ */
+public final class ArtField {
+
+ private Class<?> declaringClass;
+ /** Field access flags (modifiers) */
+ private int accessFlags;
+ /** Index into DexFile's field ids */
+ private int fieldDexIndex;
+ /** Offset of field in object or class */
+ private int offset;
+
+ /**
+ * Only created by art directly.
+ */
+ private ArtField() {}
+
+ public int getAccessFlags() {
+ return accessFlags;
+ }
+
+ int getDexFieldIndex() {
+ return fieldDexIndex;
+ }
+
+ int getOffset() {
+ return offset;
+ }
+
+ public String getName() {
+ if (fieldDexIndex == -1) {
+ // Proxy classes have 1 synthesized static field with no valid dex index
+ if (!declaringClass.isProxy()) {
+ throw new AssertionError();
+ }
+ return "throws";
+ }
+ Dex dex = declaringClass.getDex();
+ int nameIndex = dex.nameIndexFromFieldIndex(fieldDexIndex);
+ return declaringClass.getDexCacheString(dex, nameIndex);
+ }
+
+ Class<?> getDeclaringClass() {
+ return declaringClass;
+ }
+
+ Class<?> getType() {
+ if (fieldDexIndex == -1) {
+ // The type of the synthesized field in a Proxy class is Class[][]
+ if (!declaringClass.isProxy()) {
+ throw new AssertionError();
+ }
+ return Class[][].class;
+ }
+ Dex dex = declaringClass.getDex();
+ int typeIndex = dex.typeIndexFromFieldIndex(fieldDexIndex);
+ return declaringClass.getDexCacheType(dex, typeIndex);
+ }
+}
diff --git a/libart/src/main/java/java/lang/reflect/ArtMethod.java b/libart/src/main/java/java/lang/reflect/ArtMethod.java
new file mode 100644
index 0000000..5e56d87
--- /dev/null
+++ b/libart/src/main/java/java/lang/reflect/ArtMethod.java
@@ -0,0 +1,223 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.lang.reflect;
+
+import com.android.dex.Dex;
+import java.lang.annotation.Annotation;
+import libcore.reflect.AnnotationAccess;
+import libcore.reflect.InternalNames;
+import libcore.util.EmptyArray;
+
+/**
+ * This class represents methods and constructors.
+ * @hide
+ */
+public final class ArtMethod {
+
+ /** Method's declaring class */
+ private Class<?> declaringClass;
+ /** Method access flags (modifiers) */
+ private int accessFlags;
+ /** DexFile index */
+ private int methodDexIndex;
+ /** Dispatch table entry */
+ private int methodIndex;
+ /** DexFile offset of CodeItem for this Method */
+ private int codeItemOffset;
+ /* ART compiler meta-data */
+ private int frameSizeInBytes;
+ private int coreSpillMask;
+ private int fpSpillMask;
+ private int mappingTable;
+ private int gcMap;
+ private int vmapTable;
+ /** ART: compiled managed code associated with this Method */
+ private int entryPointFromCompiledCode;
+ /** ART: entry point from interpreter associated with this Method */
+ private int entryPointFromInterpreter;
+ /** ART: if this is a native method, the native code that will be invoked */
+ private int nativeMethod;
+ /* ART: dex cache fast access */
+ private String[] dexCacheStrings;
+ Class<?>[] dexCacheResolvedTypes;
+ private ArtMethod[] dexCacheResolvedMethods;
+ private Object[] dexCacheInitializedStaticStorage;
+
+ /**
+ * Only created by art directly.
+ */
+ private ArtMethod() {}
+
+ Class getDeclaringClass() {
+ return declaringClass;
+ }
+
+ public int getAccessFlags() {
+ return accessFlags;
+ }
+
+ int getDexMethodIndex() {
+ return methodDexIndex;
+ }
+
+ public static String getMethodName(ArtMethod artMethod) {
+ artMethod = artMethod.findOverriddenMethodIfProxy();
+ Dex dex = artMethod.getDeclaringClass().getDex();
+ int nameIndex = dex.nameIndexFromMethodIndex(artMethod.getDexMethodIndex());
+ // Note, in the case of a Proxy the dex cache strings are equal.
+ return artMethod.getDexCacheString(dex, nameIndex);
+ }
+
+ /**
+ * Returns true if the given parameters match those of the method in the given order.
+ *
+ * @hide
+ */
+ public static boolean equalConstructorParameters(ArtMethod artMethod, Class<?>[] params) {
+ Dex dex = artMethod.getDeclaringClass().getDex();
+ short[] types = dex.parameterTypeIndicesFromMethodIndex(artMethod.getDexMethodIndex());
+ if (types.length != params.length) {
+ return false;
+ }
+ for (int i = 0; i < types.length; i++) {
+ if (artMethod.getDexCacheType(dex, types[i]) != params[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns true if the given parameters match those of this method in the given order.
+ *
+ * @hide
+ */
+ public static boolean equalMethodParameters(ArtMethod artMethod, Class<?>[] params) {
+ return equalConstructorParameters(artMethod.findOverriddenMethodIfProxy(), params);
+ }
+
+ Class<?>[] getParameterTypes() {
+ Dex dex = getDeclaringClass().getDex();
+ short[] types = dex.parameterTypeIndicesFromMethodIndex(methodDexIndex);
+ if (types.length == 0) {
+ return EmptyArray.CLASS;
+ }
+ Class<?>[] parametersArray = new Class[types.length];
+ for (int i = 0; i < types.length; i++) {
+ // Note, in the case of a Proxy the dex cache types are equal.
+ parametersArray[i] = getDexCacheType(dex, types[i]);
+ }
+ return parametersArray;
+ }
+
+ Class<?> getReturnType() {
+ Dex dex = declaringClass.getDex();
+ int returnTypeIndex = dex.returnTypeIndexFromMethodIndex(methodDexIndex);
+ // Note, in the case of a Proxy the dex cache types are equal.
+ return getDexCacheType(dex, returnTypeIndex);
+ }
+
+ /**
+ * Performs a comparison of the parameters to this method with the given parameters.
+ *
+ * @hide
+ */
+ int compareParameters(Class<?>[] params) {
+ Dex dex = getDeclaringClass().getDex();
+ short[] types = dex.parameterTypeIndicesFromMethodIndex(methodDexIndex);
+ int length = Math.min(types.length, params.length);
+ for (int i = 0; i < length; i++) {
+ Class<?> aType = getDexCacheType(dex, types[i]);
+ Class<?> bType = params[i];
+ if (aType != bType) {
+ int comparison = aType.getName().compareTo(bType.getName());
+ if (comparison != 0) {
+ return comparison;
+ }
+ }
+ }
+ return types.length - params.length;
+ }
+
+ Annotation[][] getParameterAnnotations() {
+ return AnnotationAccess.getParameterAnnotations(declaringClass, methodDexIndex);
+ }
+
+ /**
+ * Returns a string from the dex cache, computing the string from the dex file if necessary.
+ * Note this method replicates {@link java.lang.Class#getDexCacheString(Dex, int)}, but in
+ * Method we can avoid one indirection.
+ */
+ private String getDexCacheString(Dex dex, int dexStringIndex) {
+ String s = (String) dexCacheStrings[dexStringIndex];
+ if (s == null) {
+ s = dex.strings().get(dexStringIndex);
+ dexCacheStrings[dexStringIndex] = s;
+ }
+ return s;
+ }
+
+ /**
+ * Returns a resolved type from the dex cache, computing the string from the dex file if
+ * necessary. Note this method replicates {@link java.lang.Class#getDexCacheType(Dex, int)},
+ * but in Method we can avoid one indirection.
+ */
+ private Class<?> getDexCacheType(Dex dex, int dexTypeIndex) {
+ Class<?> resolvedType = dexCacheResolvedTypes[dexTypeIndex];
+ if (resolvedType == null) {
+ int descriptorIndex = dex.typeIds().get(dexTypeIndex);
+ String descriptor = getDexCacheString(dex, descriptorIndex);
+ resolvedType = InternalNames.getClass(declaringClass.getClassLoader(),
+ descriptor);
+ dexCacheResolvedTypes[dexTypeIndex] = resolvedType;
+ }
+ return resolvedType;
+ }
+
+ /**
+ * Returns the {@code ArtMethod} that this method overrides for
+ * proxy methods, otherwise returns this method. Used to determine
+ * the interface method overridden by a proxy method (as the proxy
+ * method doesn't directly support operations such as {@link
+ * Method#getName}).
+ */
+ ArtMethod findOverriddenMethodIfProxy() {
+ if (declaringClass.isProxy()) {
+ // Proxy method's declaring class' dex cache refers to that of Proxy. The local cache in
+ // Method refers to the original interface's dex cache and is ensured to be resolved by
+ // proxy generation.
+ return dexCacheResolvedMethods[methodDexIndex];
+ }
+ return this;
+ }
+}
diff --git a/libart/src/main/java/java/lang/reflect/Constructor.java b/libart/src/main/java/java/lang/reflect/Constructor.java
index 364c7a7..62dfdfd 100644
--- a/libart/src/main/java/java/lang/reflect/Constructor.java
+++ b/libart/src/main/java/java/lang/reflect/Constructor.java
@@ -33,12 +33,10 @@
package java.lang.reflect;
import com.android.dex.Dex;
-
import java.lang.annotation.Annotation;
import java.util.Comparator;
import java.util.List;
import libcore.reflect.AnnotationAccess;
-import libcore.reflect.InternalNames;
import libcore.reflect.Types;
/**
@@ -52,9 +50,10 @@
private static final Comparator<Method> ORDER_BY_SIGNATURE = null; // Unused; must match Method.
/**
- * Only created by native code.
+ * @hide
*/
- private Constructor() {
+ public Constructor(ArtMethod artMethod) {
+ super(artMethod);
}
public Annotation[] getAnnotations() {
@@ -102,7 +101,7 @@
* this constructor has no declared exceptions, an empty array will be
* returned.
*/
- @Override public Class<?>[] getExceptionTypes() {
+ public Class<?>[] getExceptionTypes() {
// TODO: use dex cache to speed looking up class
return AnnotationAccess.getExceptions(this);
}
@@ -130,7 +129,7 @@
* as this constructor.
*/
@Override public boolean equals(Object other) {
- return this == other; // exactly one instance of each member in this runtime
+ return super.equals(other);
}
@Override public TypeVariable<Constructor<T>>[] getTypeParameters() {
@@ -214,7 +213,7 @@
* @return an array of arrays of {@code Annotation} instances
*/
public Annotation[][] getParameterAnnotations() {
- return AnnotationAccess.getParameterAnnotations(this);
+ return artMethod.getParameterAnnotations();
}
/**
@@ -284,8 +283,8 @@
*
* @see AccessibleObject
*/
- public native T newInstance(Object... args) throws InstantiationException, IllegalAccessException,
- IllegalArgumentException, InvocationTargetException;
+ public native T newInstance(Object... args) throws InstantiationException,
+ IllegalAccessException, IllegalArgumentException, InvocationTargetException;
/**
* Returns a string containing a concise, human-readable description of this
diff --git a/libart/src/main/java/java/lang/reflect/Field.java b/libart/src/main/java/java/lang/reflect/Field.java
index 55dc54b..4e982c7 100644
--- a/libart/src/main/java/java/lang/reflect/Field.java
+++ b/libart/src/main/java/java/lang/reflect/Field.java
@@ -71,18 +71,16 @@
}
};
- private Class<?> declaringClass;
- /** Field access flags (modifiers) */
- private int accessFlags;
- /** Index into DexFile's field ids */
- private int fieldDexIndex;
- /** Offset of field in object or class */
- private int offset;
+ private final ArtField artField;
/**
- * Only created by native code.
+ * @hide
*/
- private Field() {
+ public Field(ArtField artField) {
+ if (artField == null) {
+ throw new NullPointerException("artField == null");
+ }
+ this.artField = artField;
}
/**
@@ -92,8 +90,8 @@
* @return the modifiers for this field
* @see Modifier
*/
- @Override public int getModifiers() {
- return accessFlags & 0xffff; // mask out bits not used by Java
+ @Override public int getModifiers() {
+ return artField.getAccessFlags() & 0xffff; // mask out bits not used by Java
}
/**
@@ -103,7 +101,7 @@
* false} otherwise
*/
public boolean isEnumConstant() {
- return (accessFlags & Modifier.ENUM) != 0;
+ return (artField.getAccessFlags() & Modifier.ENUM) != 0;
}
/**
@@ -112,7 +110,7 @@
* @return {@code true} if this field is synthetic, {@code false} otherwise
*/
@Override public boolean isSynthetic() {
- return (accessFlags & Modifier.SYNTHETIC) != 0;
+ return (artField.getAccessFlags() & Modifier.SYNTHETIC) != 0;
}
/**
@@ -121,25 +119,11 @@
* @return the name of this field
*/
@Override public String getName() {
- if (fieldDexIndex == -1) {
- // Proxy classes have 1 synthesized static field with no valid dex index
- if (!declaringClass.isProxy()) {
- throw new AssertionError();
- }
- return "throws";
- }
- Dex dex = declaringClass.getDex();
- int nameIndex = dex.nameIndexFromFieldIndex(fieldDexIndex);
- return declaringClass.getDexCacheString(dex, nameIndex);
+ return artField.getName();
}
- /**
- * Returns the class that declares this field.
- *
- * @return the declaring class
- */
@Override public Class<?> getDeclaringClass() {
- return declaringClass;
+ return artField.getDeclaringClass();
}
/**
@@ -148,16 +132,7 @@
* @return the type of this field
*/
public Class<?> getType() {
- if (fieldDexIndex == -1) {
- // The type of the synthesized field in a Proxy class is Class[][]
- if (!declaringClass.isProxy()) {
- throw new AssertionError();
- }
- return Class[][].class;
- }
- Dex dex = declaringClass.getDex();
- int typeIndex = dex.typeIndexFromFieldIndex(fieldDexIndex);
- return declaringClass.getDexCacheType(dex, typeIndex);
+ return artField.getType();
}
/**
@@ -166,7 +141,7 @@
* @hide
*/
public int getDexFieldIndex() {
- return fieldDexIndex;
+ return artField.getDexFieldIndex();
}
/**
@@ -175,7 +150,7 @@
* @hide
*/
public int getOffset() {
- return offset;
+ return artField.getOffset();
}
/**
@@ -192,7 +167,11 @@
* as this field.
*/
@Override public boolean equals(Object other) {
- return this == other; // exactly one instance of each member in this runtime
+ if (!(other instanceof Field)) {
+ return false;
+ }
+ // exactly one instance of each member in this runtime
+ return this.artField == ((Field) other).artField;
}
/**
diff --git a/libart/src/main/java/java/lang/reflect/Method.java b/libart/src/main/java/java/lang/reflect/Method.java
index 00b51ad..1a0d5c5 100644
--- a/libart/src/main/java/java/lang/reflect/Method.java
+++ b/libart/src/main/java/java/lang/reflect/Method.java
@@ -37,7 +37,6 @@
import java.util.Comparator;
import java.util.List;
import libcore.reflect.AnnotationAccess;
-import libcore.reflect.InternalNames;
import libcore.reflect.Types;
/**
@@ -58,7 +57,8 @@
}
int comparison = a.getName().compareTo(b.getName());
if (comparison == 0) {
- comparison = a.compareParameters(b.getParameterTypes());
+ comparison = a.artMethod.findOverriddenMethodIfProxy().compareParameters(
+ b.getParameterTypes());
if (comparison == 0) {
// This is necessary for methods that have covariant return types.
Class<?> aReturnType = a.getReturnType();
@@ -75,9 +75,14 @@
};
/**
- * Only created by native code.
+ * @hide
*/
- private Method() {
+ public Method(ArtMethod artMethod) {
+ super(artMethod);
+ }
+
+ ArtMethod getArtMethod() {
+ return artMethod;
}
public Annotation[] getAnnotations() {
@@ -131,15 +136,7 @@
* @return the name of this method
*/
@Override public String getName() {
- Method method = this;
- if (declaringClass.isProxy()) {
- // For proxies use their interface method
- method = findOverriddenMethod();
- }
- Dex dex = method.declaringClass.getDex();
- int nameIndex = dex.nameIndexFromMethodIndex(methodDexIndex);
- // Note, in the case of a Proxy the dex cache strings are equal.
- return getDexCacheString(dex, nameIndex);
+ return ArtMethod.getMethodName(artMethod);
}
/**
@@ -156,7 +153,7 @@
* @return the declared exception classes
*/
public Class<?>[] getExceptionTypes() {
- if (declaringClass.isProxy()) {
+ if (getDeclaringClass().isProxy()) {
return getExceptionTypesNative();
} else {
// TODO: use dex cache to speed looking up class
@@ -174,12 +171,7 @@
* @return the parameter types
*/
@Override public Class<?>[] getParameterTypes() {
- Method method = this;
- if (declaringClass.isProxy()) {
- // For proxies use their interface method.
- return findOverriddenMethod().getParameterTypes();
- }
- return super.getParameterTypes();
+ return artMethod.findOverriddenMethodIfProxy().getParameterTypes();
}
/**
@@ -189,15 +181,7 @@
* @return the return type
*/
public Class<?> getReturnType() {
- Method method = this;
- if (declaringClass.isProxy()) {
- // For proxies use their interface method
- method = findOverriddenMethod();
- }
- Dex dex = method.declaringClass.getDex();
- int returnTypeIndex = dex.returnTypeIndexFromMethodIndex(methodDexIndex);
- // Note, in the case of a Proxy the dex cache types are equal.
- return getDexCacheType(dex, returnTypeIndex);
+ return artMethod.findOverriddenMethodIfProxy().getReturnType();
}
/**
@@ -214,7 +198,7 @@
* parameters and return type as this method.
*/
@Override public boolean equals(Object other) {
- return this == other; // exactly one instance of each member in this runtime
+ return super.equals(other);
}
/**
@@ -225,46 +209,8 @@
* @hide needed by Proxy
*/
boolean equalNameAndParameters(Method m) {
- return getName().equals(m.getName()) && equalParameters(m.getParameterTypes());
- }
-
- /**
- * Returns true if the given parameters match those of this method in the given order.
- *
- * @hide
- */
- @Override public boolean equalParameters(Class<?>[] params) {
- if (declaringClass.isProxy()) {
- // For proxies use their interface method.
- return findOverriddenMethod().equalParameters(params);
- }
- return super.equalParameters(params);
- }
-
- /**
- * Performs a comparison of the parameters to this method with the given parameters.
- *
- * @hide
- */
- int compareParameters(Class<?>[] params) {
- if (declaringClass.isProxy()) {
- // For proxies use their interface method.
- return findOverriddenMethod().compareParameters(params);
- }
- Dex dex = getDeclaringClass().getDex();
- short[] types = dex.parameterTypeIndicesFromMethodIndex(methodDexIndex);
- int length = Math.min(types.length, params.length);
- for (int i = 0; i < length; i++) {
- Class<?> aType = getDexCacheType(dex, types[i] & 0xFFFF);
- Class<?> bType = params[i];
- if (aType != bType) {
- int comparison = aType.getName().compareTo(bType.getName());
- if (comparison != 0) {
- return comparison;
- }
- }
- }
- return types.length - params.length;
+ return getName().equals(m.getName()) &&
+ ArtMethod.equalMethodParameters(artMethod,m.getParameterTypes());
}
/**
@@ -364,12 +310,7 @@
* @return an array of arrays of {@code Annotation} instances
*/
public Annotation[][] getParameterAnnotations() {
- Method method = this;
- if (declaringClass.isProxy()) {
- // For proxies use their interface method
- method = findOverriddenMethod();
- }
- return AnnotationAccess.getParameterAnnotations(method);
+ return artMethod.findOverriddenMethodIfProxy().getParameterAnnotations();
}
/**
@@ -495,26 +436,4 @@
return result.toString();
}
-
- public void setAccessible(boolean flag) {
- super.setAccessible(flag);
- }
-
- /**
- * Returns the {@code Method} that this method overrides. Used to determine the interface
- * method overridden by a proxy method (as the proxy method doesn't directly support operations
- * such as {@link Method#getName}). This method works for non-proxy methods.
- */
- private Method findOverriddenMethod() {
- if (declaringClass.isProxy()) {
- // Proxy method's declaring class' dex cache refers to that of Proxy. The local cache in
- // Method refers to the original interface's dex cache and is ensured to be resolved by
- // proxy generation. Short-cut the native call below in this case.
- return (Method) dexCacheResolvedMethods[methodDexIndex];
- } else {
- return findOverriddenMethodNative();
- }
- }
-
- private native Method findOverriddenMethodNative();
}
diff --git a/libart/src/main/java/java/lang/reflect/Proxy.java b/libart/src/main/java/java/lang/reflect/Proxy.java
index b5e6283..51b3ad5 100644
--- a/libart/src/main/java/java/lang/reflect/Proxy.java
+++ b/libart/src/main/java/java/lang/reflect/Proxy.java
@@ -162,7 +162,10 @@
validateReturnTypes(methods);
List<Class<?>[]> exceptions = deduplicateAndGetExceptions(methods);
- Method[] methodsArray = methods.toArray(new Method[methods.size()]);
+ ArtMethod[] methodsArray = new ArtMethod[methods.size()];
+ for (int i = 0; i < methodsArray.length; i++) {
+ methodsArray[i] = methods.get(i).getArtMethod();
+ }
Class<?>[][] exceptionsArray = exceptions.toArray(new Class<?>[exceptions.size()][]);
Class<?> result = generateProxy(name, interfaces, loader, methodsArray, exceptionsArray);
loader.proxyCache.put(interfacesSet, result);
@@ -362,7 +365,7 @@
}
private static native Class<?> generateProxy(String name, Class<?>[] interfaces,
- ClassLoader loader, Method[] methods,
+ ClassLoader loader, ArtMethod[] methods,
Class<?>[][] exceptions);
/*
@@ -370,4 +373,9 @@
* There is no implementation.
*/
private static native void constructorPrototype(InvocationHandler h);
+
+ static Object invoke(Proxy proxy, ArtMethod method, Object[] args) throws Throwable {
+ InvocationHandler h = proxy.h;
+ return h.invoke(proxy, new Method(method), args);
+ }
}
diff --git a/libdvm/src/main/java/java/lang/reflect/AccessibleObject.java b/libdvm/src/main/java/java/lang/reflect/AccessibleObject.java
index 9c6b8c7..f3d96af 100644
--- a/libdvm/src/main/java/java/lang/reflect/AccessibleObject.java
+++ b/libdvm/src/main/java/java/lang/reflect/AccessibleObject.java
@@ -54,7 +54,9 @@
*/
public class AccessibleObject implements AnnotatedElement {
- // If true, object is accessible, bypassing normal access checks
+ /**
+ * If true, object is accessible, bypassing normal access checks
+ */
boolean flag = false;
// Holds a mapping from Java type names to native type codes.
@@ -87,10 +89,8 @@
* @see #setAccessible(boolean)
*/
public static void setAccessible(AccessibleObject[] objects, boolean flag) {
- synchronized(AccessibleObject.class) {
- for (AccessibleObject object : objects) {
- object.flag = flag;
- }
+ for (AccessibleObject object : objects) {
+ object.flag = flag;
}
}
diff --git a/luni/src/main/java/java/lang/reflect/Modifier.java b/luni/src/main/java/java/lang/reflect/Modifier.java
index fdbe3bb..5f973d5 100644
--- a/luni/src/main/java/java/lang/reflect/Modifier.java
+++ b/luni/src/main/java/java/lang/reflect/Modifier.java
@@ -109,6 +109,13 @@
public static final int MIRANDA = 0x8000;
/**
+ * Dex addition to mark instance constructors and static class
+ * initializer methods.
+ * @hide
+ */
+ public static final int CONSTRUCTOR = 0x10000;
+
+ /**
* Constructs a new {@code Modifier} instance.
*/
public Modifier() {
@@ -239,6 +246,14 @@
}
/**
+ * Returns true if the given modifiers contain {@link Modifier#CONSTRUCTOR}.
+ * @hide
+ */
+ public static boolean isConstructor(int modifiers) {
+ return ((modifiers & Modifier.CONSTRUCTOR) != 0);
+ }
+
+ /**
* Returns a string containing the string representation of all modifiers
* present in the specified modifiers. Modifiers appear in the order
* specified by the Java Language Specification.
diff --git a/luni/src/main/java/libcore/reflect/AnnotationAccess.java b/luni/src/main/java/libcore/reflect/AnnotationAccess.java
index fe740de..3c24b08 100644
--- a/luni/src/main/java/libcore/reflect/AnnotationAccess.java
+++ b/luni/src/main/java/libcore/reflect/AnnotationAccess.java
@@ -271,15 +271,9 @@
/**
* Returns the parameter annotations on {@code member}.
*/
- public static Annotation[][] getParameterAnnotations(Member member) {
- Class<?> declaringClass = member.getDeclaringClass();
+ public static Annotation[][] getParameterAnnotations(Class<?> declaringClass,
+ int methodDexIndex) {
Dex dex = declaringClass.getDex();
- int methodDexIndex;
- if (member instanceof Method) {
- methodDexIndex = ((Method) member).getDexMethodIndex();
- } else {
- methodDexIndex = ((Constructor<?>) member).getDexMethodIndex();
- }
int protoIndex = dex.methodIds().get(methodDexIndex).getProtoIndex();
ProtoId proto = dex.protoIds().get(protoIndex);
TypeList parametersList = dex.readTypeList(proto.getParametersOffset());