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());