Skip to content

Commit 3f4e2dc

Browse files
author
Hristo Hristov
committed
Fix resolving existing DEX file.
Generate cache for declared methods per method name. Always using classCache static field when getting class from name.
1 parent 0902380 commit 3f4e2dc

4 files changed

Lines changed: 74 additions & 29 deletions

File tree

src/src/com/tns/ClassResolver.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public static Class<?> resolveClass(String fullClassName, DexFactory dexFactory,
3333

3434
if (clazz == null)
3535
{
36-
clazz = Class.forName(className);
36+
clazz = Platform.getClassForName(className);
3737
}
3838

3939
return clazz;

src/src/com/tns/DexFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ private File getDexFile(String className) throws InvalidClassException
216216
classToProxyFile += "-" + this.dexThumb;
217217
}
218218

219-
String dexFilePath = dexDir + classToProxyFile + ".dex";
219+
String dexFilePath = dexDir + "/" + classToProxyFile + ".dex";
220220
File dexFile = new File(dexFilePath);
221221
if (dexFile.exists())
222222
{

src/src/com/tns/MethodResolver.java

Lines changed: 53 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -108,23 +108,27 @@ public static String getTypeSignature(Class<?> type)
108108
return array + signature;
109109
}
110110

111-
static String resolveMethodOverload(HashMap<String, Class<?>> classCache, String className, String methodName, Object[] args) throws ClassNotFoundException
111+
static HashMap<Class<?>, MethodFinder> methodOverloadsForClass = new HashMap<Class<?>, MethodFinder>();
112+
static ArrayList<Tuple<Method, Integer>> candidates = new ArrayList<Tuple<Method, Integer>>();
113+
114+
static String resolveMethodOverload(Class<?> clazz, String methodName, Object[] args) throws ClassNotFoundException
112115
{
113-
String methodSig = null;
114-
Class<?> clazz = classCache.get(className);
115-
if (clazz == null)
116-
{
117-
clazz = Class.forName(className);
118-
}
116+
candidates.clear();
119117
int argLength = (args != null) ? args.length : 0;
120118

121-
ArrayList<Tuple<Method, Integer>> candidates = new ArrayList<Tuple<Method, Integer>>();
122-
123119
Class<?> c = clazz;
124120
int iterationIndex = 0;
125121
while (c != null)
126122
{
127-
tryFindMatches(methodName, candidates, args, argLength, c.getDeclaredMethods());
123+
MethodFinder finder = methodOverloadsForClass.get(c);
124+
if (finder == null)
125+
{
126+
finder = new MethodFinder(c);
127+
methodOverloadsForClass.put(c, finder);
128+
}
129+
130+
ArrayList<Method> matchingMethods = finder.getMatchingMethods(methodName);
131+
tryFindMatches(methodName, candidates, args, argLength, matchingMethods);
128132
if (candidates.size() > iterationIndex && candidates.get(iterationIndex).y == 0)
129133
{
130134
// direct matching (distance 0) found
@@ -139,28 +143,18 @@ static String resolveMethodOverload(HashMap<String, Class<?>> classCache, String
139143
{
140144
if (candidates.size() > 1)
141145
Collections.sort(candidates, distanceComparator);
146+
142147
Method method = candidates.get(0).x;
143-
methodSig = getMethodSignature(method.getReturnType(), method.getParameterTypes());
148+
return getMethodSignature(method.getReturnType(), method.getParameterTypes());
144149
}
145150

146-
return methodSig;
151+
return null;
147152
}
148153

149-
static void tryFindMatches(String methodName, ArrayList<Tuple<Method, Integer>> candidates, Object[] args, int argLength, Method[] methods)
154+
static void tryFindMatches(String methodName, ArrayList<Tuple<Method, Integer>> candidates, Object[] args, int argLength, ArrayList<Method> methods)
150155
{
151156
for (Method method : methods)
152157
{
153-
if (!method.getName().equals(methodName))
154-
{
155-
continue;
156-
}
157-
158-
int modifiers = method.getModifiers();
159-
if (!Modifier.isPublic(modifiers) && !Modifier.isProtected(modifiers))
160-
{
161-
continue;
162-
}
163-
164158
Class<?>[] params = method.getParameterTypes();
165159

166160
boolean success = false;
@@ -620,4 +614,38 @@ else if (primitiveType.equals(boolean.class))
620614

621615
return success;
622616
}
623-
}
617+
618+
static class MethodFinder {
619+
private Method[] declaredMethods;
620+
private HashMap<String, ArrayList<Method>> matchingMethods = new HashMap<String, ArrayList<Method>>();
621+
public MethodFinder(Class<?> clazz) {
622+
this.declaredMethods = clazz.getDeclaredMethods();
623+
}
624+
625+
public ArrayList<Method> getMatchingMethods(String methodName) {
626+
ArrayList<Method> matches = this.matchingMethods.get(methodName);
627+
if (matches == null) {
628+
matches = new ArrayList<Method>();
629+
for (Method method : this.declaredMethods)
630+
{
631+
if (!method.getName().equals(methodName))
632+
{
633+
continue;
634+
}
635+
636+
int modifiers = method.getModifiers();
637+
if (!Modifier.isPublic(modifiers) && !Modifier.isProtected(modifiers))
638+
{
639+
continue;
640+
}
641+
642+
matches.add(method);
643+
}
644+
645+
matchingMethods.put(methodName, matches);
646+
}
647+
648+
return matches;
649+
}
650+
}
651+
}

src/src/com/tns/Platform.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ private static String[] getTypeMetadata(String className, int index) throws Clas
395395
if (clazz == null)
396396
{
397397
clazz = Class.forName(className);
398+
classCache.put(className, clazz);
398399
}
399400
}
400401

@@ -750,13 +751,29 @@ static Object[] packageArgs(Object... args)
750751

751752
return packagedArgs;
752753
}
754+
755+
static Class<?> getClassForName(String className) throws ClassNotFoundException {
756+
Class<?> clazz = classCache.get(className);
757+
if (clazz == null)
758+
{
759+
clazz = Class.forName(className);
760+
if (clazz != null) {
761+
classCache.put(className, clazz);
762+
}
763+
}
764+
765+
return clazz;
766+
}
753767

754768
@RuntimeCallable
755769
private static String resolveMethodOverload(String className, String methodName, Object[] args) throws Exception
756770
{
757771
if (logger.isEnabled())
758772
logger.write("resolveMethodOverload: Resolving method " + methodName + " on class " + className);
759-
String res = MethodResolver.resolveMethodOverload(classCache, className, methodName, args);
773+
774+
Class<?> clazz = getClassForName(className);
775+
776+
String res = MethodResolver.resolveMethodOverload(clazz, methodName, args);
760777
if (logger.isEnabled())
761778
logger.write("resolveMethodOverload: method found :" + res);
762779
if (res == null)
@@ -902,7 +919,7 @@ public static void purgeAllProxies()
902919
@RuntimeCallable
903920
private static Object createArrayHelper(String arrayClassName, int size) throws ClassNotFoundException
904921
{
905-
Class<?> clazz = Class.forName(arrayClassName);
922+
Class<?> clazz = getClassForName(arrayClassName);
906923

907924
Object arr = Array.newInstance(clazz, size);
908925

0 commit comments

Comments
 (0)