• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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