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 46 /** Method's declaring class */ 47 private Class<?> declaringClass; 48 /** Method access flags (modifiers) */ 49 private int accessFlags; 50 /** DexFile index */ 51 private int methodDexIndex; 52 /** Dispatch table entry */ 53 private int methodIndex; 54 /** DexFile offset of CodeItem for this Method */ 55 private int codeItemOffset; 56 /* ART compiler meta-data */ 57 private int frameSizeInBytes; 58 private int coreSpillMask; 59 private int fpSpillMask; 60 private int mappingTable; 61 private int gcMap; 62 private int vmapTable; 63 /** ART: compiled managed code associated with this Method */ 64 private int entryPointFromCompiledCode; 65 /** ART: entry point from interpreter associated with this Method */ 66 private int entryPointFromInterpreter; 67 /** ART: if this is a native method, the native code that will be invoked */ 68 private int nativeMethod; 69 /* ART: dex cache fast access */ 70 private String[] dexCacheStrings; 71 Class<?>[] dexCacheResolvedTypes; 72 private ArtMethod[] dexCacheResolvedMethods; 73 private Object[] dexCacheInitializedStaticStorage; 74 75 /** 76 * Only created by art directly. 77 */ 78 private ArtMethod() {} 79 80 Class getDeclaringClass() { 81 return declaringClass; 82 } 83 84 public int getAccessFlags() { 85 return accessFlags; 86 } 87 88 int getDexMethodIndex() { 89 return methodDexIndex; 90 } 91 92 public static String getMethodName(ArtMethod artMethod) { 93 artMethod = artMethod.findOverriddenMethodIfProxy(); 94 Dex dex = artMethod.getDeclaringClass().getDex(); 95 int nameIndex = dex.nameIndexFromMethodIndex(artMethod.getDexMethodIndex()); 96 // Note, in the case of a Proxy the dex cache strings are equal. 97 return artMethod.getDexCacheString(dex, nameIndex); 98 } 99 100 /** 101 * Returns true if the given parameters match those of the method in the given order. 102 * 103 * @hide 104 */ 105 public static boolean equalConstructorParameters(ArtMethod artMethod, Class<?>[] params) { 106 Dex dex = artMethod.getDeclaringClass().getDex(); 107 short[] types = dex.parameterTypeIndicesFromMethodIndex(artMethod.getDexMethodIndex()); 108 if (types.length != params.length) { 109 return false; 110 } 111 for (int i = 0; i < types.length; i++) { 112 if (artMethod.getDexCacheType(dex, types[i]) != params[i]) { 113 return false; 114 } 115 } 116 return true; 117 } 118 119 /** 120 * Returns true if the given parameters match those of this method in the given order. 121 * 122 * @hide 123 */ 124 public static boolean equalMethodParameters(ArtMethod artMethod, Class<?>[] params) { 125 return equalConstructorParameters(artMethod.findOverriddenMethodIfProxy(), params); 126 } 127 128 Class<?>[] getParameterTypes() { 129 Dex dex = getDeclaringClass().getDex(); 130 short[] types = dex.parameterTypeIndicesFromMethodIndex(methodDexIndex); 131 if (types.length == 0) { 132 return EmptyArray.CLASS; 133 } 134 Class<?>[] parametersArray = new Class[types.length]; 135 for (int i = 0; i < types.length; i++) { 136 // Note, in the case of a Proxy the dex cache types are equal. 137 parametersArray[i] = getDexCacheType(dex, types[i]); 138 } 139 return parametersArray; 140 } 141 142 Class<?> getReturnType() { 143 Dex dex = declaringClass.getDex(); 144 int returnTypeIndex = dex.returnTypeIndexFromMethodIndex(methodDexIndex); 145 // Note, in the case of a Proxy the dex cache types are equal. 146 return getDexCacheType(dex, returnTypeIndex); 147 } 148 149 /** 150 * Performs a comparison of the parameters to this method with the given parameters. 151 * 152 * @hide 153 */ 154 int compareParameters(Class<?>[] params) { 155 Dex dex = getDeclaringClass().getDex(); 156 short[] types = dex.parameterTypeIndicesFromMethodIndex(methodDexIndex); 157 int length = Math.min(types.length, params.length); 158 for (int i = 0; i < length; i++) { 159 Class<?> aType = getDexCacheType(dex, types[i]); 160 Class<?> bType = params[i]; 161 if (aType != bType) { 162 int comparison = aType.getName().compareTo(bType.getName()); 163 if (comparison != 0) { 164 return comparison; 165 } 166 } 167 } 168 return types.length - params.length; 169 } 170 171 Annotation[][] getParameterAnnotations() { 172 return AnnotationAccess.getParameterAnnotations(declaringClass, methodDexIndex); 173 } 174 175 /** 176 * Returns a string from the dex cache, computing the string from the dex file if necessary. 177 * Note this method replicates {@link java.lang.Class#getDexCacheString(Dex, int)}, but in 178 * Method we can avoid one indirection. 179 */ 180 private String getDexCacheString(Dex dex, int dexStringIndex) { 181 String s = (String) dexCacheStrings[dexStringIndex]; 182 if (s == null) { 183 s = dex.strings().get(dexStringIndex).intern(); 184 dexCacheStrings[dexStringIndex] = s; 185 } 186 return s; 187 } 188 189 /** 190 * Returns a resolved type from the dex cache, computing the string from the dex file if 191 * necessary. Note this method delegates to {@link java.lang.Class#getDexCacheType(Dex, int)}, 192 * but in Method we can avoid one indirection. 193 */ 194 private Class<?> getDexCacheType(Dex dex, int dexTypeIndex) { 195 Class<?> resolvedType = dexCacheResolvedTypes[dexTypeIndex]; 196 if (resolvedType == null) { 197 resolvedType = declaringClass.getDexCacheType(dex, dexTypeIndex); 198 } 199 return resolvedType; 200 } 201 202 /** 203 * Returns the {@code ArtMethod} that this method overrides for 204 * proxy methods, otherwise returns this method. Used to determine 205 * the interface method overridden by a proxy method (as the proxy 206 * method doesn't directly support operations such as {@link 207 * Method#getName}). 208 */ 209 ArtMethod findOverriddenMethodIfProxy() { 210 if (declaringClass.isProxy()) { 211 // Proxy method's declaring class' dex cache refers to that of Proxy. The local cache in 212 // Method refers to the original interface's dex cache and is ensured to be resolved by 213 // proxy generation. 214 return dexCacheResolvedMethods[methodDexIndex]; 215 } 216 return this; 217 } 218 } 219