Closed sunxiaobiu closed 3 years ago
@tom-ystang 可以给一些排查思路吗?谢谢orz
我找到原因了,tinker确实已经执行成功,且加载了我新增的class。我的问题是出在我试图用反射从dex里面获取指定包下的所有classes,这个过程失败了,没有获取成功。应该是需要从TinkerClassLoder获取dexElements,然后拿到里面的dexFile List,然后解析指定包下面的class,但是貌似TinkerClassLoder没有把这些信息放到field里面,所以反射调用不到。。。这个目前我还不知道要怎么弄。。
我解决了。用一下代码即可:
public static ArrayList<String> findClassesStartWith(String prefix) {
try {
ArrayList<String> result = new ArrayList<>();
ArrayList<DexFile> dexFiles = findAllDexFiles(Thread.currentThread().getContextClassLoader());
for (DexFile dexFile : dexFiles) {
Enumeration<String> classNames = dexFile.entries();
while (classNames.hasMoreElements()) {
String className = classNames.nextElement();
if (className.startsWith(prefix)) {
result.add(className);
}
}
}
return result;
} catch (Exception ignored) {
}
return null;
}
public static ArrayList<DexFile> findAllDexFiles(ClassLoader classLoader) {
ArrayList<DexFile> dexFiles = new ArrayList<>();
try {
Field pathListField = findField(classLoader, "pathList");
Object pathList = pathListField.get(classLoader);
Field dexElementsField = findField(pathList, "dexElements");
Object[] dexElements = (Object[]) dexElementsField.get(pathList);
Field dexFileField = findField(dexElements[0], "dexFile");
for (Object dexElement : dexElements) {
Object dexFile = dexFileField.get(dexElement);
dexFiles.add((DexFile) dexFile);
}
} catch (Exception e) {
e.printStackTrace();
}
return dexFiles;
}
private static Field findField(Object instance, String name) throws NoSuchFieldException {
Class clazz = instance.getClass();
while (clazz != null) {
try {
Field field = clazz.getDeclaredField(name);
if (!field.isAccessible()) {
field.setAccessible(true);
}
return field;
} catch (NoSuchFieldException var4) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException("Field " + name + " not found in " + instance.getClass());
}
Issue/提问须知
在提交issue之前,我们应该先查询是否已经有相关的issue以及常见问题。提交issue时,我们需要写明issue的原因,以及编译或运行过程的日志(加载进程以及Patch进程)。issue需要以下面的格式: