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 /** Short-cut to declaringClass.dexCache.strings */ 57 private String[] dexCacheStrings; 58 59 /** 60 * Method dispatch from the interpreter invokes this pointer which may cause a bridge into 61 * compiled code. 62 */ 63 private long entryPointFromInterpreter; 64 65 /** 66 * Pointer to JNI function registered to this method, or a function to resolve the JNI function. 67 */ 68 private long entryPointFromJni; 69 70 /** 71 * Method dispatch from portable compiled code invokes this pointer which may cause bridging 72 * into quick compiled code or the interpreter. 73 * Uncomment to enable. 74 */ 75 // private long entryPointFromPortableCompiledCode; 76 77 /** 78 * Method dispatch from quick compiled code invokes this pointer which may cause bridging 79 * into portable compiled code or the interpreter. 80 */ 81 private long entryPointFromQuickCompiledCode; 82 83 /** 84 * Pointer to a data structure created by the compiler and used by the garbage collector to 85 * determine which registers hold live references to objects within the heap. 86 */ 87 private long gcMap; 88 89 /** Bits encoding access (e.g. public, private) as well as other runtime specific flags */ 90 private int accessFlags; 91 92 /* Dex file fields. The defining dex file is available via declaringClass.dexCache */ 93 94 /** The offset of the code item associated with this method within its defining dex file */ 95 private int dexCodeItemOffset; 96 97 /** The method index of this method within its defining dex file */ 98 private int dexMethodIndex; 99 100 /* End of dex file fields. */ 101 102 /** 103 * Entry within a dispatch table for this method. For static/direct methods the index is 104 * into the declaringClass.directMethods, for virtual methods the vtable and for 105 * interface methods the ifTable. 106 */ 107 private int methodIndex; 108 109 /** Only created by ART directly. */ ArtMethod()110 private ArtMethod() {} 111 getDeclaringClass()112 Class getDeclaringClass() { 113 return declaringClass; 114 } 115 getAccessFlags()116 public int getAccessFlags() { 117 return accessFlags; 118 } 119 getDexMethodIndex()120 int getDexMethodIndex() { 121 return dexMethodIndex; 122 } 123 getMethodName(ArtMethod artMethod)124 public static String getMethodName(ArtMethod artMethod) { 125 artMethod = artMethod.findOverriddenMethodIfProxy(); 126 Dex dex = artMethod.getDeclaringClass().getDex(); 127 int nameIndex = dex.nameIndexFromMethodIndex(artMethod.getDexMethodIndex()); 128 // Note, in the case of a Proxy the dex cache strings are equal. 129 return artMethod.getDexCacheString(dex, nameIndex); 130 } 131 132 /** 133 * Returns true if the given parameters match those of the method in the given order. 134 * 135 * @hide 136 */ equalConstructorParameters(ArtMethod artMethod, Class<?>[] params)137 public static boolean equalConstructorParameters(ArtMethod artMethod, Class<?>[] params) { 138 Dex dex = artMethod.getDeclaringClass().getDex(); 139 short[] types = dex.parameterTypeIndicesFromMethodIndex(artMethod.getDexMethodIndex()); 140 if (types.length != params.length) { 141 return false; 142 } 143 for (int i = 0; i < types.length; i++) { 144 if (artMethod.getDexCacheType(dex, types[i]) != params[i]) { 145 return false; 146 } 147 } 148 return true; 149 } 150 151 /** 152 * Returns true if the given parameters match those of this method in the given order. 153 * 154 * @hide 155 */ equalMethodParameters(ArtMethod artMethod, Class<?>[] params)156 public static boolean equalMethodParameters(ArtMethod artMethod, Class<?>[] params) { 157 return equalConstructorParameters(artMethod.findOverriddenMethodIfProxy(), params); 158 } 159 getParameterTypes()160 Class<?>[] getParameterTypes() { 161 Dex dex = getDeclaringClass().getDex(); 162 short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex); 163 if (types.length == 0) { 164 return EmptyArray.CLASS; 165 } 166 Class<?>[] parametersArray = new Class[types.length]; 167 for (int i = 0; i < types.length; i++) { 168 // Note, in the case of a Proxy the dex cache types are equal. 169 parametersArray[i] = getDexCacheType(dex, types[i]); 170 } 171 return parametersArray; 172 } 173 getReturnType()174 Class<?> getReturnType() { 175 Dex dex = declaringClass.getDex(); 176 int returnTypeIndex = dex.returnTypeIndexFromMethodIndex(dexMethodIndex); 177 // Note, in the case of a Proxy the dex cache types are equal. 178 return getDexCacheType(dex, returnTypeIndex); 179 } 180 181 /** 182 * Performs a comparison of the parameters to this method with the given parameters. 183 * 184 * @hide 185 */ compareParameters(Class<?>[] params)186 int compareParameters(Class<?>[] params) { 187 Dex dex = getDeclaringClass().getDex(); 188 short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex); 189 int length = Math.min(types.length, params.length); 190 for (int i = 0; i < length; i++) { 191 Class<?> aType = getDexCacheType(dex, types[i]); 192 Class<?> bType = params[i]; 193 if (aType != bType) { 194 int comparison = aType.getName().compareTo(bType.getName()); 195 if (comparison != 0) { 196 return comparison; 197 } 198 } 199 } 200 return types.length - params.length; 201 } 202 getParameterAnnotations()203 Annotation[][] getParameterAnnotations() { 204 return AnnotationAccess.getParameterAnnotations(declaringClass, dexMethodIndex); 205 } 206 207 /** 208 * Returns a string from the dex cache, computing the string from the dex file if necessary. 209 * Note this method replicates {@link java.lang.Class#getDexCacheString(Dex, int)}, but in 210 * Method we can avoid one indirection. 211 */ getDexCacheString(Dex dex, int dexStringIndex)212 private String getDexCacheString(Dex dex, int dexStringIndex) { 213 String s = (String) dexCacheStrings[dexStringIndex]; 214 if (s == null) { 215 s = dex.strings().get(dexStringIndex).intern(); 216 dexCacheStrings[dexStringIndex] = s; 217 } 218 return s; 219 } 220 221 /** 222 * Returns a resolved type from the dex cache, computing the string from the dex file if 223 * necessary. Note this method delegates to {@link java.lang.Class#getDexCacheType(Dex, int)}, 224 * but in Method we can avoid one indirection. 225 */ getDexCacheType(Dex dex, int dexTypeIndex)226 private Class<?> getDexCacheType(Dex dex, int dexTypeIndex) { 227 Class<?> resolvedType = dexCacheResolvedTypes[dexTypeIndex]; 228 if (resolvedType == null) { 229 resolvedType = declaringClass.getDexCacheType(dex, dexTypeIndex); 230 } 231 return resolvedType; 232 } 233 234 /** 235 * Returns the {@code ArtMethod} that this method overrides for 236 * proxy methods, otherwise returns this method. Used to determine 237 * the interface method overridden by a proxy method (as the proxy 238 * method doesn't directly support operations such as {@link 239 * Method#getName}). 240 */ findOverriddenMethodIfProxy()241 ArtMethod findOverriddenMethodIfProxy() { 242 if (declaringClass.isProxy()) { 243 // Proxy method's declaring class' dex cache refers to that of Proxy. The local cache in 244 // Method refers to the original interface's dex cache and is ensured to be resolved by 245 // proxy generation. 246 return dexCacheResolvedMethods[dexMethodIndex]; 247 } 248 return this; 249 } 250 } 251