summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dex/src/main/java/com/android/dex/Dex.java207
-rw-r--r--dex/src/main/java/com/android/dex/TypeList.java2
-rw-r--r--libart/src/main/java/java/lang/Class.java6
-rw-r--r--libart/src/main/java/java/lang/reflect/AbstractMethod.java45
-rw-r--r--libart/src/main/java/java/lang/reflect/Constructor.java51
-rw-r--r--libart/src/main/java/java/lang/reflect/Field.java15
-rw-r--r--libart/src/main/java/java/lang/reflect/Method.java132
7 files changed, 259 insertions, 199 deletions
diff --git a/dex/src/main/java/com/android/dex/Dex.java b/dex/src/main/java/com/android/dex/Dex.java
index 29cd30ea7..bf249985f 100644
--- a/dex/src/main/java/com/android/dex/Dex.java
+++ b/dex/src/main/java/com/android/dex/Dex.java
@@ -53,7 +53,9 @@ public final class Dex {
private static final int CHECKSUM_SIZE = 4;
private static final int SIGNATURE_OFFSET = CHECKSUM_OFFSET + CHECKSUM_SIZE;
private static final int SIGNATURE_SIZE = 20;
-
+ // Provided as a convenience to avoid a memory allocation to benefit Dalvik.
+ // Note: libcore.util.EmptyArray cannot be accessed when this code isn't run on Dalvik.
+ static final short[] EMPTY_SHORT_ARRAY = new short[0];
private ByteBuffer data;
private final TableOfContents tableOfContents = new TableOfContents();
private int nextSectionStart = 0;
@@ -450,6 +452,9 @@ public final class Dex {
}
public short[] readShortArray(int length) {
+ if (length == 0) {
+ return EMPTY_SHORT_ARRAY;
+ }
short[] result = new short[length];
for (int i = 0; i < length; i++) {
result[i] = readShort();
@@ -475,10 +480,7 @@ public final class Dex {
public TypeList readTypeList() {
int size = readInt();
- short[] types = new short[size];
- for (int i = 0; i < size; i++) {
- types[i] = readShort();
- }
+ short[] types = readShortArray(size);
alignToFourBytes();
return new TypeList(Dex.this, types);
}
@@ -552,71 +554,71 @@ public final class Dex {
Try[] tries;
CatchHandler[] catchHandlers;
if (triesSize > 0) {
- if (instructions.length % 2 == 1) {
- readShort(); // padding
- }
-
- /*
- * We can't read the tries until we've read the catch handlers.
- * Unfortunately they're in the opposite order in the dex file
- * so we need to read them out-of-order.
- */
- Section triesSection = open(data.position());
- skip(triesSize * SizeOf.TRY_ITEM);
- catchHandlers = readCatchHandlers();
- tries = triesSection.readTries(triesSize, catchHandlers);
- } else {
- tries = new Try[0];
- catchHandlers = new CatchHandler[0];
- }
- return new Code(registersSize, insSize, outsSize, debugInfoOffset, instructions,
- tries, catchHandlers);
+ if (instructions.length % 2 == 1) {
+ readShort(); // padding
+ }
+
+ /*
+ * We can't read the tries until we've read the catch handlers.
+ * Unfortunately they're in the opposite order in the dex file
+ * so we need to read them out-of-order.
+ */
+ Section triesSection = open(data.position());
+ skip(triesSize * SizeOf.TRY_ITEM);
+ catchHandlers = readCatchHandlers();
+ tries = triesSection.readTries(triesSize, catchHandlers);
+ } else {
+ tries = new Try[0];
+ catchHandlers = new CatchHandler[0];
+ }
+ return new Code(registersSize, insSize, outsSize, debugInfoOffset, instructions,
+ tries, catchHandlers);
}
private CatchHandler[] readCatchHandlers() {
- int baseOffset = data.position();
- int catchHandlersSize = readUleb128();
- CatchHandler[] result = new CatchHandler[catchHandlersSize];
- for (int i = 0; i < catchHandlersSize; i++) {
- int offset = data.position() - baseOffset;
- result[i] = readCatchHandler(offset);
- }
- return result;
+ int baseOffset = data.position();
+ int catchHandlersSize = readUleb128();
+ CatchHandler[] result = new CatchHandler[catchHandlersSize];
+ for (int i = 0; i < catchHandlersSize; i++) {
+ int offset = data.position() - baseOffset;
+ result[i] = readCatchHandler(offset);
+ }
+ return result;
}
private Try[] readTries(int triesSize, CatchHandler[] catchHandlers) {
- Try[] result = new Try[triesSize];
- for (int i = 0; i < triesSize; i++) {
- int startAddress = readInt();
- int instructionCount = readUnsignedShort();
- int handlerOffset = readUnsignedShort();
- int catchHandlerIndex = findCatchHandlerIndex(catchHandlers, handlerOffset);
- result[i] = new Try(startAddress, instructionCount, catchHandlerIndex);
- }
- return result;
+ Try[] result = new Try[triesSize];
+ for (int i = 0; i < triesSize; i++) {
+ int startAddress = readInt();
+ int instructionCount = readUnsignedShort();
+ int handlerOffset = readUnsignedShort();
+ int catchHandlerIndex = findCatchHandlerIndex(catchHandlers, handlerOffset);
+ result[i] = new Try(startAddress, instructionCount, catchHandlerIndex);
+ }
+ return result;
}
private int findCatchHandlerIndex(CatchHandler[] catchHandlers, int offset) {
- for (int i = 0; i < catchHandlers.length; i++) {
- CatchHandler catchHandler = catchHandlers[i];
- if (catchHandler.getOffset() == offset) {
- return i;
+ for (int i = 0; i < catchHandlers.length; i++) {
+ CatchHandler catchHandler = catchHandlers[i];
+ if (catchHandler.getOffset() == offset) {
+ return i;
+ }
}
- }
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException();
}
private CatchHandler readCatchHandler(int offset) {
- int size = readSleb128();
- int handlersCount = Math.abs(size);
- int[] typeIndexes = new int[handlersCount];
- int[] addresses = new int[handlersCount];
- for (int i = 0; i < handlersCount; i++) {
- typeIndexes[i] = readUleb128();
- addresses[i] = readUleb128();
- }
- int catchAllAddress = size <= 0 ? readUleb128() : -1;
- return new CatchHandler(typeIndexes, addresses, catchAllAddress, offset);
+ int size = readSleb128();
+ int handlersCount = Math.abs(size);
+ int[] typeIndexes = new int[handlersCount];
+ int[] addresses = new int[handlersCount];
+ for (int i = 0; i < handlersCount; i++) {
+ typeIndexes[i] = readUleb128();
+ addresses[i] = readUleb128();
+ }
+ int catchAllAddress = size <= 0 ? readUleb128() : -1;
+ return new CatchHandler(typeIndexes, addresses, catchAllAddress, offset);
}
private ClassData readClassData() {
@@ -680,11 +682,11 @@ public final class Dex {
}
public void skip(int count) {
- if (count < 0) {
- throw new IllegalArgumentException();
- }
- data.position(data.position() + count);
- }
+ if (count < 0) {
+ throw new IllegalArgumentException();
+ }
+ data.position(data.position() + count);
+ }
/**
* Skips bytes until the position is aligned to a multiple of 4.
@@ -788,4 +790,85 @@ public final class Dex {
return data.position() - initialPosition;
}
}
+
+ /**
+ * Look up a field id name index from a field index. Equivalent to:
+ * {@code fieldIds().get(fieldDexIndex).getNameIndex();}
+ */
+ public int nameIndexFromFieldIndex(int fieldIndex) {
+ checkBounds(fieldIndex, tableOfContents.fieldIds.size);
+ int position = tableOfContents.fieldIds.off + (SizeOf.MEMBER_ID_ITEM * fieldIndex);
+ position += SizeOf.USHORT; // declaringClassIndex
+ position += SizeOf.USHORT; // typeIndex
+ return data.getInt(position); // nameIndex
+ }
+
+ /**
+ * Look up a field id type index from a field index. Equivalent to:
+ * {@code fieldIds().get(fieldDexIndex).getTypeIndex();}
+ */
+ public int typeIndexFromFieldIndex(int fieldIndex) {
+ checkBounds(fieldIndex, tableOfContents.fieldIds.size);
+ int position = tableOfContents.fieldIds.off + (SizeOf.MEMBER_ID_ITEM * fieldIndex);
+ position += SizeOf.USHORT; // declaringClassIndex
+ return data.getShort(position) & 0xFFFF; // typeIndex
+ }
+
+ /**
+ * Look up a method id name index from a method index. Equivalent to:
+ * {@code methodIds().get(methodIndex).getNameIndex();}
+ */
+ public int nameIndexFromMethodIndex(int methodIndex) {
+ checkBounds(methodIndex, tableOfContents.methodIds.size);
+ int position = tableOfContents.methodIds.off + (SizeOf.MEMBER_ID_ITEM * methodIndex);
+ position += SizeOf.USHORT; // declaringClassIndex
+ position += SizeOf.USHORT; // protoIndex
+ return data.getInt(position); // nameIndex
+ }
+
+ /**
+ * Lookup a parameter type ids from a method index. Equivalent to:
+ * {@code readTypeList(protoIds.get(methodIds().get(methodDexIndex).getProtoIndex()).getParametersOffset()).getTypes();}
+ */
+ public short[] parameterTypeIndicesFromMethodIndex(int methodIndex) {
+ checkBounds(methodIndex, tableOfContents.methodIds.size);
+ int position = tableOfContents.methodIds.off + (SizeOf.MEMBER_ID_ITEM * methodIndex);
+ position += SizeOf.USHORT; // declaringClassIndex
+ int protoIndex = data.getShort(position) & 0xFFFF;
+ checkBounds(protoIndex, tableOfContents.protoIds.size);
+ position = tableOfContents.protoIds.off + (SizeOf.PROTO_ID_ITEM * protoIndex);
+ position += SizeOf.UINT; // shortyIndex
+ position += SizeOf.UINT; // returnTypeIndex
+ int parametersOffset = data.getInt(position);
+ if (parametersOffset == 0) {
+ return EMPTY_SHORT_ARRAY;
+ }
+ position = parametersOffset;
+ int size = data.getInt(position);
+ if (size <= 0) {
+ throw new AssertionError("Unexpected parameter type list size: " + size);
+ }
+ position += SizeOf.UINT;
+ short[] types = new short[size];
+ for (int i = 0; i < size; i++) {
+ types[i] = data.getShort(position);
+ position += SizeOf.USHORT;
+ }
+ return types;
+ }
+
+ /**
+ * Look up a method id return type index from a method index. Equivalent to:
+ * {@code protoIds().get(methodIds().get(methodDexIndex).getProtoIndex()).getReturnTypeIndex();}
+ */
+ public int returnTypeIndexFromMethodIndex(int methodIndex) {
+ checkBounds(methodIndex, tableOfContents.methodIds.size);
+ int position = tableOfContents.methodIds.off + (SizeOf.MEMBER_ID_ITEM * methodIndex);
+ position += SizeOf.USHORT; // declaringClassIndex
+ int protoIndex = data.getShort(position) & 0xFFFF;
+ checkBounds(protoIndex, tableOfContents.protoIds.size);
+ position = tableOfContents.protoIds.off + (SizeOf.PROTO_ID_ITEM * protoIndex);
+ position += SizeOf.UINT; // shortyIndex
+ return data.getInt(position); // returnTypeIndex
+ }
}
diff --git a/dex/src/main/java/com/android/dex/TypeList.java b/dex/src/main/java/com/android/dex/TypeList.java
index 6e321fbd7..123e82c9a 100644
--- a/dex/src/main/java/com/android/dex/TypeList.java
+++ b/dex/src/main/java/com/android/dex/TypeList.java
@@ -20,7 +20,7 @@ import com.android.dex.util.Unsigned;
public final class TypeList implements Comparable<TypeList> {
- public static final TypeList EMPTY = new TypeList(null, new short[0]);
+ public static final TypeList EMPTY = new TypeList(null, Dex.EMPTY_SHORT_ARRAY);
private final Dex dex;
private final short[] types;
diff --git a/libart/src/main/java/java/lang/Class.java b/libart/src/main/java/java/lang/Class.java
index 044bb0463..0d0b64d45 100644
--- a/libart/src/main/java/java/lang/Class.java
+++ b/libart/src/main/java/java/lang/Class.java
@@ -520,7 +520,7 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe
private Constructor<T> getDeclaredConstructorInternal(Class<?>[] args) {
if (directMethods != null) {
for (AbstractMethod m : directMethods) {
- if (m instanceof Constructor && Arrays.equals(args, m.getParameterTypes())) {
+ if (m instanceof Constructor && m.equalParameters(args)) {
return (Constructor<T>) m;
}
}
@@ -671,7 +671,7 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe
Method result = null;
if (virtualMethods != null) {
for (Method m : virtualMethods) {
- if (name.equals(m.getName()) && Arrays.equals(args, m.getParameterTypes())) {
+ if (name.equals(m.getName()) && m.equalParameters(args)) {
int modifiers = m.getAccessFlags();
if ((modifiers & skipModifiers) == 0) {
return m;
@@ -686,7 +686,7 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe
if (directMethods != null) {
for (AbstractMethod m : directMethods) {
if (m instanceof Method && name.equals(m.getName()) &&
- Arrays.equals(args, m.getParameterTypes())) {
+ m.equalParameters(args)) {
int modifiers = m.getAccessFlags();
if ((modifiers & skipModifiers) == 0) {
return (Method) m;
diff --git a/libart/src/main/java/java/lang/reflect/AbstractMethod.java b/libart/src/main/java/java/lang/reflect/AbstractMethod.java
index ba7c0c35b..c1412e154 100644
--- a/libart/src/main/java/java/lang/reflect/AbstractMethod.java
+++ b/libart/src/main/java/java/lang/reflect/AbstractMethod.java
@@ -45,6 +45,7 @@ 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.
@@ -152,7 +153,12 @@ public abstract class AbstractMethod extends AccessibleObject {
return declaringClass;
}
- public int getDexMethodIndex() {
+ /**
+ * Returns the index of this method's ID in its dex file.
+ *
+ * @hide
+ */
+ public final int getDexMethodIndex() {
return methodDexIndex;
}
@@ -180,7 +186,38 @@ public abstract class AbstractMethod extends AccessibleObject {
*
* @return the parameter types
*/
- public abstract Class<?>[] getParameterTypes();
+ 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]);
+ }
+ 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]) != params[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
/**
* Returns true if {@code other} has the same declaring class, name,
@@ -243,7 +280,7 @@ public abstract class AbstractMethod extends AccessibleObject {
* Note this method replicates {@link java.lang.Class#getDexCacheString(Dex, int)}, but in
* Method we can avoid one indirection.
*/
- String getDexCacheString(Dex dex, int dexStringIndex) {
+ final String getDexCacheString(Dex dex, int dexStringIndex) {
String s = (String) dexCacheStrings[dexStringIndex];
if (s == null) {
s = dex.strings().get(dexStringIndex);
@@ -257,7 +294,7 @@ public abstract class AbstractMethod extends AccessibleObject {
* necessary. Note this method replicates {@link java.lang.Class#getDexCacheType(Dex, int)},
* but in Method we can avoid one indirection.
*/
- Class<?> getDexCacheType(Dex dex, int dexTypeIndex) {
+ final Class<?> getDexCacheType(Dex dex, int dexTypeIndex) {
Class<?> resolvedType = dexCacheResolvedTypes[dexTypeIndex];
if (resolvedType == null) {
int descriptorIndex = dex.typeIds().get(dexTypeIndex);
diff --git a/libart/src/main/java/java/lang/reflect/Constructor.java b/libart/src/main/java/java/lang/reflect/Constructor.java
index 982653be1..364c7a778 100644
--- a/libart/src/main/java/java/lang/reflect/Constructor.java
+++ b/libart/src/main/java/java/lang/reflect/Constructor.java
@@ -33,8 +33,6 @@
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.Comparator;
@@ -93,15 +91,6 @@ public final class Constructor<T> extends AbstractMethod implements GenericDecla
}
/**
- * Returns the index of this constructor's method ID in its dex file.
- *
- * @hide used by AnnotationAccess
- */
- public int getDexMethodIndex() {
- return super.getDexMethodIndex();
- }
-
- /**
* Returns the class that declares this constructor.
*/
@Override public Class<T> getDeclaringClass() {
@@ -124,16 +113,7 @@ public final class Constructor<T> extends AbstractMethod implements GenericDecla
* no parameters, an empty array will be returned.
*/
public Class<?>[] getParameterTypes() {
- Dex dex = declaringClass.getDex();
- int protoIndex = dex.methodIds().get(methodDexIndex).getProtoIndex();
- ProtoId proto = dex.protoIds().get(protoIndex);
- TypeList parametersList = dex.readTypeList(proto.getParametersOffset());
- short[] types = parametersList.getTypes();
- Class<?>[] parametersArray = new Class[types.length];
- for (int i = 0; i < types.length; i++) {
- parametersArray[i] = getDexCacheType(dex, types[i]);
- }
- return parametersArray;
+ return super.getParameterTypes();
}
/**
@@ -344,33 +324,4 @@ public final class Constructor<T> extends AbstractMethod implements GenericDecla
return result.toString();
}
-
- /**
- * 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.
- *
- * @hide
- */
- String getDexCacheString(Dex dex, int dexStringIndex) {
- return super.getDexCacheString(dex, dexStringIndex);
- }
-
- /**
- * 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.
- *
- * @hide
- */
- 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;
- }
}
diff --git a/libart/src/main/java/java/lang/reflect/Field.java b/libart/src/main/java/java/lang/reflect/Field.java
index 2d0570a9f..55dc54b06 100644
--- a/libart/src/main/java/java/lang/reflect/Field.java
+++ b/libart/src/main/java/java/lang/reflect/Field.java
@@ -54,11 +54,20 @@ public final class Field extends AccessibleObject implements Member {
public static final Comparator<Field> ORDER_BY_NAME_AND_DECLARING_CLASS
= new Comparator<Field>() {
@Override public int compare(Field a, Field b) {
+ if (a == b) {
+ return 0;
+ }
int comparison = a.getName().compareTo(b.getName());
if (comparison != 0) {
return comparison;
}
- return a.getDeclaringClass().getName().compareTo(b.getDeclaringClass().getName());
+ Class<?> aType = a.getDeclaringClass();
+ Class<?> bType = b.getDeclaringClass();
+ if (aType == bType) {
+ return 0;
+ } else {
+ return aType.getName().compareTo(bType.getName());
+ }
}
};
@@ -120,7 +129,7 @@ public final class Field extends AccessibleObject implements Member {
return "throws";
}
Dex dex = declaringClass.getDex();
- int nameIndex = dex.fieldIds().get(fieldDexIndex).getNameIndex();
+ int nameIndex = dex.nameIndexFromFieldIndex(fieldDexIndex);
return declaringClass.getDexCacheString(dex, nameIndex);
}
@@ -147,7 +156,7 @@ public final class Field extends AccessibleObject implements Member {
return Class[][].class;
}
Dex dex = declaringClass.getDex();
- int typeIndex = dex.fieldIds().get(fieldDexIndex).getTypeIndex();
+ int typeIndex = dex.typeIndexFromFieldIndex(fieldDexIndex);
return declaringClass.getDexCacheType(dex, typeIndex);
}
diff --git a/libart/src/main/java/java/lang/reflect/Method.java b/libart/src/main/java/java/lang/reflect/Method.java
index 555afc9c8..5096745f3 100644
--- a/libart/src/main/java/java/lang/reflect/Method.java
+++ b/libart/src/main/java/java/lang/reflect/Method.java
@@ -33,11 +33,7 @@
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;
@@ -61,23 +57,20 @@ public final class Method extends AbstractMethod implements GenericDeclaration,
return 0;
}
int comparison = a.getName().compareTo(b.getName());
- if (comparison != 0) {
- return comparison;
- }
- Class<?>[] aParameters = a.getParameterTypes();
- Class<?>[] bParameters = b.getParameterTypes();
- int length = Math.min(aParameters.length, bParameters.length);
- for (int i = 0; i < length; i++) {
- comparison = aParameters[i].getName().compareTo(bParameters[i].getName());
- if (comparison != 0) {
- return comparison;
+ if (comparison == 0) {
+ comparison = a.compareParameters(b.getParameterTypes());
+ if (comparison == 0) {
+ // This is necessary for methods that have covariant return types.
+ Class<?> aReturnType = a.getReturnType();
+ Class<?> bReturnType = b.getReturnType();
+ if (aReturnType == bReturnType) {
+ comparison = 0;
+ } else {
+ comparison = aReturnType.getName().compareTo(bReturnType.getName());
+ }
}
}
- if (aParameters.length != bParameters.length) {
- return aParameters.length - bParameters.length;
- }
- // this is necessary for methods that have covariant return types.
- return a.getReturnType().getName().compareTo(b.getReturnType().getName());
+ return comparison;
}
};
@@ -144,7 +137,7 @@ public final class Method extends AbstractMethod implements GenericDeclaration,
method = findOverriddenMethod();
}
Dex dex = method.declaringClass.getDex();
- int nameIndex = dex.methodIds().get(methodDexIndex).getNameIndex();
+ int nameIndex = dex.nameIndexFromMethodIndex(methodDexIndex);
// Note, in the case of a Proxy the dex cache strings are equal.
return getDexCacheString(dex, nameIndex);
}
@@ -157,15 +150,6 @@ public final class Method extends AbstractMethod implements GenericDeclaration,
}
/**
- * Returns the index of this method's ID in its dex file.
- *
- * @hide
- */
- public int getDexMethodIndex() {
- return super.getDexMethodIndex();
- }
-
- /**
* Returns the exception types as an array of {@code Class} instances. If
* this method has no declared exceptions, an empty array is returned.
*
@@ -189,23 +173,13 @@ public final class Method extends AbstractMethod implements GenericDeclaration,
*
* @return the parameter types
*/
- public Class<?>[] getParameterTypes() {
+ @Override public Class<?>[] getParameterTypes() {
Method method = this;
if (declaringClass.isProxy()) {
- // For proxies use their interface method
- method = findOverriddenMethod();
- }
- Dex dex = method.declaringClass.getDex();
- int protoIndex = dex.methodIds().get(methodDexIndex).getProtoIndex();
- ProtoId proto = dex.protoIds().get(protoIndex);
- TypeList parametersList = dex.readTypeList(proto.getParametersOffset());
- short[] types = parametersList.getTypes();
- 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]);
+ // For proxies use their interface method.
+ return findOverriddenMethod().getParameterTypes();
}
- return parametersArray;
+ return super.getParameterTypes();
}
/**
@@ -221,9 +195,7 @@ public final class Method extends AbstractMethod implements GenericDeclaration,
method = findOverriddenMethod();
}
Dex dex = method.declaringClass.getDex();
- int proto_idx = dex.methodIds().get(methodDexIndex).getProtoIndex();
- ProtoId proto = dex.protoIds().get(proto_idx);
- int returnTypeIndex = proto.getReturnTypeIndex();
+ int returnTypeIndex = dex.returnTypeIndexFromMethodIndex(methodDexIndex);
// Note, in the case of a Proxy the dex cache types are equal.
return getDexCacheType(dex, returnTypeIndex);
}
@@ -253,13 +225,46 @@ public final class Method extends AbstractMethod implements GenericDeclaration,
* @hide needed by Proxy
*/
boolean equalNameAndParameters(Method m) {
- if (!getName().equals(m.getName())) {
- return false;
+ 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);
}
- if (!Arrays.equals(getParameterTypes(), m.getParameterTypes())) {
- return false;
+ 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 < types.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 true;
+ return types.length - params.length;
}
/**
@@ -496,31 +501,6 @@ public final class Method extends AbstractMethod implements GenericDeclaration,
}
/**
- * 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.
- */
- String getDexCacheString(Dex dex, int dexStringIndex) {
- return super.getDexCacheString(dex, dexStringIndex);
- }
-
- /**
- * 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.
- */
- 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 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.