1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 /* 18 * Copyright (C) 2012 The Android Open Source Project 19 * 20 * Licensed under the Apache License, Version 2.0 (the "License"); 21 * you may not use this file except in compliance with the License. 22 * You may obtain a copy of the License at 23 * 24 * http://www.apache.org/licenses/LICENSE-2.0 25 * 26 * Unless required by applicable law or agreed to in writing, software 27 * distributed under the License is distributed on an "AS IS" BASIS, 28 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 29 * See the License for the specific language governing permissions and 30 * limitations under the License. 31 */ 32 33 package java.lang.reflect; 34 35 import com.android.dex.Dex; 36 import java.lang.annotation.Annotation; 37 import libcore.reflect.AnnotationAccess; 38 import libcore.util.EmptyArray; 39 40 /** 41 * This class represents methods and constructors. 42 * @hide 43 */ 44 public final class ArtMethod { 45 /* A note on the field order here, it reflects the same field order as laid out by ART. */ 46 47 /** Method's declaring class */ 48 private Class<?> declaringClass; 49 50 /** Short-cut to declaringClass.dexCache.resolvedMethods */ 51 private ArtMethod[] dexCacheResolvedMethods; 52 53 /** Short-cut to declaringClass.dexCache.resolvedTypes */ 54 /* package */ Class<?>[] dexCacheResolvedTypes; 55 56 /** Bits encoding access (e.g. public, private) as well as other runtime specific flags */ 57 private int accessFlags; 58 59 /* Dex file fields. The defining dex file is available via declaringClass.dexCache */ 60 61 /** The offset of the code item associated with this method within its defining dex file */ 62 private int dexCodeItemOffset; 63 64 /** The method index of this method within its defining dex file */ 65 private int dexMethodIndex; 66 67 /* End of dex file fields. */ 68 69 /** 70 * Entry within a dispatch table for this method. For static/direct methods the index is 71 * into the declaringClass.directMethods, for virtual methods the vtable and for 72 * interface methods the ifTable. 73 */ 74 private int methodIndex; 75 76 /** Only created by ART directly. */ ArtMethod()77 private ArtMethod() {} 78 getDeclaringClass()79 Class getDeclaringClass() { 80 return declaringClass; 81 } 82 getAccessFlags()83 public int getAccessFlags() { 84 return accessFlags; 85 } 86 getDexMethodIndex()87 int getDexMethodIndex() { 88 return dexMethodIndex; 89 } 90 getMethodName(ArtMethod artMethod)91 public static String getMethodName(ArtMethod artMethod) { 92 artMethod = artMethod.findOverriddenMethodIfProxy(); 93 Dex dex = artMethod.getDeclaringClass().getDex(); 94 int nameIndex = dex.nameIndexFromMethodIndex(artMethod.getDexMethodIndex()); 95 // Note, in the case of a Proxy the dex cache strings are equal. 96 return artMethod.getDexCacheString(dex, nameIndex); 97 } 98 99 /** 100 * Returns true if the given parameters match those of the method in the given order. 101 * 102 * @hide 103 */ equalConstructorParameters(ArtMethod artMethod, Class<?>[] params)104 public static boolean equalConstructorParameters(ArtMethod artMethod, Class<?>[] params) { 105 Dex dex = artMethod.getDeclaringClass().getDex(); 106 short[] types = dex.parameterTypeIndicesFromMethodIndex(artMethod.getDexMethodIndex()); 107 if (types.length != params.length) { 108 return false; 109 } 110 for (int i = 0; i < types.length; i++) { 111 if (artMethod.getDexCacheType(dex, types[i]) != params[i]) { 112 return false; 113 } 114 } 115 return true; 116 } 117 118 /** 119 * Returns true if the given parameters match those of this method in the given order. 120 * 121 * @hide 122 */ equalMethodParameters(ArtMethod artMethod, Class<?>[] params)123 public static boolean equalMethodParameters(ArtMethod artMethod, Class<?>[] params) { 124 return equalConstructorParameters(artMethod.findOverriddenMethodIfProxy(), params); 125 } 126 getParameterTypes()127 Class<?>[] getParameterTypes() { 128 Dex dex = getDeclaringClass().getDex(); 129 short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex); 130 if (types.length == 0) { 131 return EmptyArray.CLASS; 132 } 133 Class<?>[] parametersArray = new Class[types.length]; 134 for (int i = 0; i < types.length; i++) { 135 // Note, in the case of a Proxy the dex cache types are equal. 136 parametersArray[i] = getDexCacheType(dex, types[i]); 137 } 138 return parametersArray; 139 } 140 getReturnType()141 Class<?> getReturnType() { 142 Dex dex = declaringClass.getDex(); 143 int returnTypeIndex = dex.returnTypeIndexFromMethodIndex(dexMethodIndex); 144 // Note, in the case of a Proxy the dex cache types are equal. 145 return getDexCacheType(dex, returnTypeIndex); 146 } 147 148 /** 149 * Performs a comparison of the parameters to this method with the given parameters. 150 * 151 * @hide 152 */ compareParameters(Class<?>[] params)153 int compareParameters(Class<?>[] params) { 154 Dex dex = getDeclaringClass().getDex(); 155 short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex); 156 int length = Math.min(types.length, params.length); 157 for (int i = 0; i < length; i++) { 158 Class<?> aType = getDexCacheType(dex, types[i]); 159 Class<?> bType = params[i]; 160 if (aType != bType) { 161 int comparison = aType.getName().compareTo(bType.getName()); 162 if (comparison != 0) { 163 return comparison; 164 } 165 } 166 } 167 return types.length - params.length; 168 } 169 getParameterAnnotations()170 Annotation[][] getParameterAnnotations() { 171 return AnnotationAccess.getParameterAnnotations(declaringClass, dexMethodIndex); 172 } 173 174 /** 175 * Returns a string from the dex cache, computing the string from the dex file if necessary. 176 * Note this method replicates {@link java.lang.Class#getDexCacheString(Dex, int)}, but in 177 * Method we can avoid one indirection. 178 */ getDexCacheString(Dex dex, int dexStringIndex)179 private String getDexCacheString(Dex dex, int dexStringIndex) { 180 return declaringClass.getDexCacheString(dex, dexStringIndex); 181 } 182 183 /** 184 * Returns a resolved type from the dex cache, computing the string from the dex file if 185 * necessary. Note this method delegates to {@link java.lang.Class#getDexCacheType(Dex, int)}, 186 * but in Method we can avoid one indirection. 187 */ getDexCacheType(Dex dex, int dexTypeIndex)188 private Class<?> getDexCacheType(Dex dex, int dexTypeIndex) { 189 Class<?> resolvedType = dexCacheResolvedTypes[dexTypeIndex]; 190 if (resolvedType == null) { 191 resolvedType = declaringClass.getDexCacheType(dex, dexTypeIndex); 192 } 193 return resolvedType; 194 } 195 196 /** 197 * Returns the {@code ArtMethod} that this method overrides for 198 * proxy methods, otherwise returns this method. Used to determine 199 * the interface method overridden by a proxy method (as the proxy 200 * method doesn't directly support operations such as {@link 201 * Method#getName}). 202 */ findOverriddenMethodIfProxy()203 ArtMethod findOverriddenMethodIfProxy() { 204 if (declaringClass.isProxy()) { 205 // Proxy method's declaring class' dex cache refers to that of Proxy. The local cache in 206 // Method refers to the original interface's dex cache and is ensured to be resolved by 207 // proxy generation. 208 return dexCacheResolvedMethods[dexMethodIndex]; 209 } 210 return this; 211 } 212 } 213