1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.os.instrumentation; 18 19 import android.annotation.NonNull; 20 21 import java.lang.reflect.Executable; 22 23 /** 24 * A utility class for dynamic instrumentation / uprobestats. 25 * 26 * @hide 27 */ 28 public final class MethodDescriptorParser { 29 30 /** 31 * Parses a {@link MethodDescriptor} (in string representation) into a {@link Executable}. 32 */ parseMethodDescriptor(ClassLoader classLoader, @NonNull MethodDescriptor descriptor)33 public static Executable parseMethodDescriptor(ClassLoader classLoader, 34 @NonNull MethodDescriptor descriptor) { 35 try { 36 Class<?> javaClass = classLoader.loadClass(descriptor.fullyQualifiedClassName); 37 Class<?>[] parameters = new Class[descriptor.fullyQualifiedParameters.length]; 38 for (int i = 0; i < descriptor.fullyQualifiedParameters.length; i++) { 39 String typeName = descriptor.fullyQualifiedParameters[i]; 40 boolean isArrayType = typeName.endsWith("[]"); 41 if (isArrayType) { 42 typeName = typeName.substring(0, typeName.length() - 2); 43 } 44 switch (typeName) { 45 case "boolean": 46 parameters[i] = isArrayType ? boolean.class.arrayType() : boolean.class; 47 break; 48 case "byte": 49 parameters[i] = isArrayType ? byte.class.arrayType() : byte.class; 50 break; 51 case "char": 52 parameters[i] = isArrayType ? char.class.arrayType() : char.class; 53 break; 54 case "short": 55 parameters[i] = isArrayType ? short.class.arrayType() : short.class; 56 break; 57 case "int": 58 parameters[i] = isArrayType ? int.class.arrayType() : int.class; 59 break; 60 case "long": 61 parameters[i] = isArrayType ? long.class.arrayType() : long.class; 62 break; 63 case "float": 64 parameters[i] = isArrayType ? float.class.arrayType() : float.class; 65 break; 66 case "double": 67 parameters[i] = isArrayType ? double.class.arrayType() : double.class; 68 break; 69 default: 70 parameters[i] = isArrayType ? classLoader.loadClass(typeName).arrayType() 71 : classLoader.loadClass(typeName); 72 } 73 } 74 75 if (com.android.art.flags.Flags.executableMethodFileOffsetsV2() 76 && descriptor.methodName.equals("<init>")) { 77 return javaClass.getDeclaredConstructor(parameters); 78 } 79 return javaClass.getDeclaredMethod(descriptor.methodName, parameters); 80 } catch (ClassNotFoundException | NoSuchMethodException e) { 81 throw new IllegalArgumentException( 82 "The specified method cannot be found. Is this descriptor valid? " 83 + descriptor, e); 84 } 85 } 86 } 87