当前位置:网站首页>BaseDexClassLoader的正确使用方式
BaseDexClassLoader的正确使用方式
2022-08-09 04:15:00 【失落夏天】
前言:
今天解决一个插件化问题的时候,竟然发现SO没有正常加载,很怪异,最终排查下来发现竟然是参数传入错误导致的。这就扯到了本文的标题上了,BaseDexClassLoader中的4个参数该如何传入,传入的又是什么呢?
一共有4个参数,分来来讲。
1:dexFile(String类型) 2:optimizedDirectory(File类型) 3:librarySearchPath(String类型) 4:parent(ClassLoader类型)
一.dexPath(String)
官方的注释:
* @param dexPath the list of jar/apk files containing classes and
* resources, delimited by {@code File.pathSeparator}, which
* defaults to {@code ":"} on Android.包含类和类的jar/apk文件列表资源,由{@code File.pathSeparator}分隔,其中Android上的默认值为{@code”:“}。
也就是说这里其实是可以传入一个集合的。
比如如下的参数都是可以被接受的:
sdcard/test/aa.apk
sdcard/test/aa.apk:sdcard/test/bb.apk:sdcard/test/cc.apk
sdcard/test/aa.apk:sdcard/test/dd.jar
其中分隔符:,保险起见,可以使用File.pathSeparator替代。
示例代码如下:
private void loadDex(List<File> apkList) {
StringBuilder builder = new StringBuilder();
for (File f : apkList) {
builder.append(f.getAbsolutePath());
builder.append(File.separatorChar);
}
DexClassLoader dexClassLoader = new DexClassLoader(builder.toString(), null, null, getClass().getClassLoader());
}二.optimizedDirectory
官方的注释:
this parameter is deprecated and has no effect since API level 26.解压的路径,这里传入路径的最主要目的就是为了生成odex文件夹,方便后续存储odex文件。
如注释中所写,这个参数26开始已经失效了。所以这里就不扩展去讲了。
三.librarySearchPath
官方的注释:
* @param librarySearchPath the list of directories containing native包含native目录的目录列表,这里要注意的,传入的一定是so的上一级目录才可以。如果是更上一层的目录是不行的。前言中的问题就出在这,传入了一个更上一层的目录地址。
排查流程:
最终使用librarySearchPath的地方是在DexPathList的splitPaths方法中。生成File加入List中:
@UnsupportedAppUsage
private static List<File> splitPaths(String searchPath, boolean directoriesOnly) {
List<File> result = new ArrayList<>();
if (searchPath != null) {
for (String path : searchPath.split(File.pathSeparator)) {
...
result.add(new File(path));
}
}
return result;
}而使用的时候,是使用了findLibrary的方法,for循环便利上面集合中的所有path,看是否存在。
public String findLibrary(String libraryName) {
String fileName = System.mapLibraryName(libraryName);
for (NativeLibraryElement element : nativeLibraryPathElements) {
String path = element.findNativeLibrary(fileName);
if (path != null) {
return path;
}
}
return null;
}而寻找的最终会调用到NativeLibraryElement的findNativeLibrary方法:
public String findNativeLibrary(String name) {
maybeInit();
if (zipDir == null) {
String entryPath = new File(path, name).getPath();
if (IoUtils.canOpenReadOnly(entryPath)) {
return entryPath;
}
} else if (urlHandler != null) {
// Having a urlHandler means the element has a zip file.
// In this case Android supports loading the library iff
// it is stored in the zip uncompressed.
String entryName = zipDir + '/' + name;
if (urlHandler.isEntryStored(entryName)) {
return path.getPath() + zipSeparator + entryName;
}
}
return null;
}这段代码也就是问题的核心了,直接使用了new File(path,name)的方式,而不是循环查找,所以只有上一层才可以。
四.parent
官方的注释:
@param parent the parent class loader这个比较简单,就是上一层的classLoader。
五.总结
无论是dexPath还是librarySearchPath,都是支持多路径传入的。路径之间使用File.pathSeparator进行分隔。dexPath中必须是APK或者Jar包的路径,而librarySearchPath中必须是so文件的上一层级文件夹才可以。
边栏推荐
猜你喜欢

Crosstalk and Protection

服务端修改Cookie——跨域cookie发送机——通信加密——异或加密

助力To B业务,这类企业端数据值得风控童鞋关注

If A, B, C, and D process parts, the total number of processed parts is 370. If the number of parts processed by A is 10 more, if the number of parts processed by B is 20 less, if the number of parts

容易混淆的指针知识点

Flask框架实现异步处理请求

Talking about the process and how to create it

2022年低压电工练习题及模拟考试

337. Robbery III

driftingblues靶机wp
随机推荐
NanoDet代码逐行精读与修改(五.1)检测头的构造和前向传播
JVM学习——1——虚拟机基础概念
Gopacket source code analysis
NanoDet代码逐行精读与修改(三)辅助训练模块AGM
月报总结|Moonbeam 7月份大事一览
从暴力递归到动态规划leetcode第62题:不同路径
Query the size of the total points obtained in a certain time period to sort
TASSEL软件导入plink格式文件报错
技术分享 | 使用 cURL 发送请求
高效回顾深度学习DL、CV、NLP
器件可靠性与温度的关系
Device Reliability vs. Temperature
OpenCV相机标定完全指南(有手就行)
松柏集(江风起)
31 基本统计概念
STM32串口通信不停接受到垃圾数据的问题及其解决
31 basic statistical concepts
2022年熔化焊接与热切割考试模拟100题及在线模拟考试
Swift3.0 sets the background color and text color of the status bar
自动化测试-图片中添加文字注释,添加到allure测试报告中