1 // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 package org.jetbrains.java.decompiler.modules.decompiler;
4 import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor;
5 import org.jetbrains.java.decompiler.struct.gen.VarType;
7 import java.lang.reflect.Method;
8 import java.util.Collections;
9 import java.util.HashMap;
12 public final class ClasspathHelper {
14 private static final Map<String, Method> METHOD_CACHE = Collections.synchronizedMap(new HashMap<>());
16 public static Method findMethod(String classname, String methodName, MethodDescriptor descriptor) {
17 String targetClass = classname.replace('/', '.');
18 String methodSignature = buildMethodSignature(targetClass + '.' + methodName, descriptor);
21 if (METHOD_CACHE.containsKey(methodSignature)) {
22 method = METHOD_CACHE.get(methodSignature);
25 method = findMethodOnClasspath(targetClass, methodSignature);
26 METHOD_CACHE.put(methodSignature, method);
32 private static Method findMethodOnClasspath(String targetClass, String methodSignature) {
34 // use bootstrap classloader to only provide access to JRE classes
35 Class cls = new ClassLoader(null) {}.loadClass(targetClass);
36 for (Method mtd : cls.getMethods()) {
37 // use contains() to ignore access modifiers and thrown exceptions
38 if (mtd.toString().contains(methodSignature)) {
49 private static String buildMethodSignature(String name, MethodDescriptor md) {
50 StringBuilder sb = new StringBuilder();
52 appendType(sb, md.ret);
53 sb.append(' ').append(name).append('(');
54 for (VarType param : md.params) {
55 appendType(sb, param);
58 if (sb.charAt(sb.length() - 1) == ',') {
59 sb.setLength(sb.length() - 1);
66 private static void appendType(StringBuilder sb, VarType type) {
67 sb.append(type.value.replace('/', '.'));
68 for (int i = 0; i < type.arrayDim; i++) {