android PathClassLoader DexClassLoader BaseDexClassLoader
来源:互联网 发布:hpm136扫描软件 编辑:程序博客网 时间:2024/05/13 17:52
android PathClassLoader DexClassLoader BaseDexClassLoader
Android类加载器:
BootClassLoader,URLClassLoader,PathClassLoader,DexClassLoader,BaseDexClassLoader等最终都继承自java.lang.ClassLoader,
//1、ClassLoader中loadClass()函数
Android中的ClassLoader与Java有些不同,Android中ClassLoader加载的是dex文件,而Java中加载的是jar文件.相同的是两者都采用了双亲委派模型.
其他的子类都继承了此方法且没有进行复写.
protected Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException { Class<?> clazz = findLoadedClass(className); // 检查Class是否已加载过 if (clazz == null) { ClassNotFoundException suppressed = null; try { clazz = parent.loadClass(className, false); //使用parent ClassLoader去加载Class } catch (ClassNotFoundException e) { suppressed = e; } if (clazz == null) { try { clazz = findClass(className); // 加载不成功,调用findClass函数来获取class对象. } catch (ClassNotFoundException e) { e.addSuppressed(suppressed); throw e; } } } return clazz;}
2、PathClassLoader和DexClassLoader都继承自BaseDexClassLoader,其主要逻辑都是在BaseDexClassLoader完成
public class BaseDexClassLoader extends ClassLoader{
…
/**
* Constructs an instance.
*
* @param dexPath:the list of jar/apk files containing classes and resources, delimited by {@code File.pathSeparator}, which defaults to {@code “:”} on Android
* @param optimizedDirectory:directory where optimized dex files should be written; may be {@code null}
* @param libraryPath:the list of directories containing native libraries, delimited by {@code File.pathSeparator}; may be{@code null}
* @param parent:the parent class loader
*/
/*
dexPath:
指目标类所在的APK或jar文件的路径, 类装载器将从该路径中寻找指定的目标类, 该类必须是APK或jar的全路径.
如果要包含多个路径,路径之间必须使用特定的分割符分隔,特定的分割符可以使用System.getProperty(“path.separtor”)获得。
上面”支持加载APK、DEX和JAR,也可以从SD卡进行加载”指的就是这个路径,
最终做的是将dexPath路径上的文件ODEX优化到内部位置optimizedDirectory,然后再进行加载的。
optimizedDirectory: (必须是一个内部存储路径,是用来缓存我们需要加载的dex文件的,并创建一个DexFile对象,如果它为null,直接使用dex文件原有的路径来创建DexFile对象)
由于dex文件被包含在APK或者Jar文件中,因此在装载目标类之前需要先从APK或Jar文件中解压出dex文件,该参数就是制定解压出的dex文件存放的路径。
这也是对apk中dex根据平台进行ODEX优化的过程。其实APK是一个程序压缩包,里面包含dex文件,ODEX优化就是把包里面的执行程序提取出来,就变成ODEX文件,
只有第一次会解压执行程序到 /data/dalvik-cache(针对PathClassLoader)或者optimizedDirectory(针对DexClassLoader)目录,之后是直接读取目录下的的dex文件。
libPath:
指目标类中所使用的C/C++库存放的路径
classload:
是指该装载器的父装载器,一般为当前执行类的装载器,例如在Android中以context.getClassLoader()作为父装载器
*/
public BaseDexClassLoader(String dexPath, File optimizedDirectory, String libraryPath, ClassLoader parent) { super(parent); this.originalPath = dexPath; this.pathList = new DexPathList(this, dexPath, libraryPath, optimizedDirectory); //BaseDexClassLoder的构造函数使用入参的三个路径构造了一个DexPathList对象.// DexPathList -> Element(makeDexElements()) -> DexFile(loadDexFile()->loadDex()->DexFile()->openDexFile()) } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { Class clazz = pathList.findClass(name); //使用DexPathList的findClass()函数,返回找到的. if (clazz == null) { throw new ClassNotFoundException(name); } return clazz; } //more code}
//DexClassLoader还需要指定一个生成优化后的apk的路径optimizedDirectory。而PathClassLoader则不需要,因为在安装阶段已经生成了/data/dalvik-cache/xxx@classes.dex
//可以从包含classes.dex实体的.jar或.apk文件中加载classes的类加载器。可以用于实现dex的动态加载、代码热更新等
public class DexClassLoader extends BaseDexClassLoader { //可以加载jar/apk/dex,可以从SD卡中加载未安装的apk
public DexClassLoader(String dexPath, String optimizedDirectory, String libraryPath, ClassLoader parent) { super(dexPath, new File(optimizedDirectory), libraryPath, parent); //直接调用BaseDexClassLoader的构造函数 }}
//PathClassLoader的super调用中,optimizedDirectory一直为null.
(也就是没设置优化后的存放路径optimizedDirectory,实际上optimizedDirectory为null时的默认路径就是/data/dalvik-cache目录,PathClassLoader是用来加载Android系统类和应用的类,不建议开发者直接使用)
public class PathClassLoader extends BaseDexClassLoader { //只能加载系统中已经安装过的apk public PathClassLoader(String dexPath, ClassLoader parent) { super(dexPath, null, null, parent); //直接调用BaseDexClassLoader的构造函数 } public PathClassLoader(String dexPath, String libraryPath, ClassLoader parent) { super(dexPath, null, libraryPath, parent); }}
3、
final class DexPathList { /** list of dex/resource (class path) elements */ private final Element[] dexElements; public DexPathList(ClassLoader definingContext, String dexPath, String libraryPath, File optimizedDirectory) { // some error checking this.definingContext = definingContext; this.dexElements = makeDexElements(splitDexPath(dexPath), optimizedDirectory); //传入的dexPath、optimizedDirectory路径转化为Element数组 this.nativeLibraryDirectories = splitLibraryPath(libraryPath); } public Class findClass(String name) { for (Element element : dexElements) { //遍历dexElements中的DexFile来加载Class DexFile dex = element.dexFile; if (dex != null) { Class clazz = dex.loadClassBinaryName(name, definingContext); if (clazz != null) { return clazz; } } } return null; } static class Element { public final File file; public final ZipFile zipFile; public final DexFile dexFile; }}
//Element数组的生成过程
/** * Makes an array of dex/resource path elements, one per element of * the given array. */private static Element[] makeDexElements(ArrayList<File> files, File optimizedDirectory) { ArrayList<Element> elements = new ArrayList<Element>(); for (File file : files) { ZipFile zip = null; DexFile dex = null; String name = file.getName(); if (name.endsWith(DEX_SUFFIX)) { // 文件后缀为.dex try { dex = loadDexFile(file, optimizedDirectory); //1、 loadDexFile()来生成dex对象 } catch (IOException ex) { System.logE("Unable to load dex file: " + file, ex); } } else if (name.endsWith(APK_SUFFIX) || name.endsWith(JAR_SUFFIX) || name.endsWith(ZIP_SUFFIX)) {// 文件后缀为apk,jar,zip try { zip = new ZipFile(file); //构造zip对象 } catch (IOException ex) { System.logE("Unable to open zip file: " + file, ex); } try { dex = loadDexFile(file, optimizedDirectory); //2、loadDexFile()来生成dex对象 } catch (IOException ignored) { // 如果压缩文件中没有dex文件,抛出这个异常,可以直接无视 } } else { System.logW("Unknown file type for: " + file); } if ((zip != null) || (dex != null)) { //如果同时有zip和dex文件,就构造对应的Element elements.add(new Element(file, zip, dex)); } } return elements.toArray(new Element[elements.size()]);}typedef struct DexFile { /* directly-mapped "opt" header */ const DexOptHeader* pOptHeader; /* pointers to directly-mapped structs and arrays in base DEX */ const DexHeader* pHeader; const DexStringId* pStringIds; const DexTypeId* pTypeIds; const DexFieldId* pFieldIds; const DexMethodId* pMethodIds; const DexProtoId* pProtoIds; const DexClassDef* pClassDefs; const DexLink* pLinkData; /* * These are mapped out of the "auxillary" section, and may not be * included in the file. */ const DexClassLookup* pClassLookup; const void* pRegisterMapPool; // RegisterMapClassPool /* points to start of DEX file data */ const u1* baseAddr; /* track memory overhead for auxillary structures */ int overhead; /* additional app-specific data structures associated with the DEX */ //void* auxData; } DexFile;
//loadDexFile()调用loadDex()创建 DexFile
private static DexFile loadDexFile(File file, File optimizedDirectory) throws IOException { if (optimizedDirectory == null) { return new DexFile(file); } else { String optimizedPath = optimizedPathFor(file, optimizedDirectory); //根据optimizedDirectory是否为null调用不同的方法来构造DexFile return DexFile.loadDex(file.getPath(), optimizedPath, 0); }}/** * Converts a dex/jar file path and an output directory to an * output file path for an associated optimized dex file. */private static String optimizedPathFor(File path, File optimizedDirectory) { String fileName = path.getName(); if (!fileName.endsWith(DEX_SUFFIX)) { int lastDot = fileName.lastIndexOf("."); if (lastDot < 0) { fileName += DEX_SUFFIX; } else { StringBuilder sb = new StringBuilder(lastDot + 4); sb.append(fileName, 0, lastDot); sb.append(DEX_SUFFIX); fileName = sb.toString(); } } File result = new File(optimizedDirectory, fileName); return result.getPath();}
//loadDex()实例化DexFile类
static public DexFile loadDex(String sourcePathName, String outputPathName, int flags) throws IOException { /* * TODO: we may want to cache previously-opened DexFile objects. * The cache would be synchronized with close(). This would help * us avoid mapping the same DEX more than once when an app decided to open it multiple times. In practice this may not be a real issue. */ return new DexFile(sourcePathName, outputPathName, flags); }
//DexFile类调用openDexFile()
private DexFile(String sourceName, String outputName, int flags) throws IOException { String wantDex = System.getProperty("android.vm.dexfile", "false"); if (!wantDex.equals("true")) throw new UnsupportedOperationException("No dex in this VM"); mCookie = openDexFile(sourceName, outputName, flags); // 调用openDexFile() (native函数) mFileName = sourceName; //System.out.println("DEX FILE cookie is " + mCookie); }
// java code
native private static int openDexFile(String sourceName, String outputName, int flags) throws IOException; // outputName就是optimizedDirectory,PathClassLoader和DexClassLoader的区别是optimizedDirectory是否为null,对应openDexFile()中outputName是否为null
// native code
static void Dalvik_dalvik_system_DexFile_openDexFile(const u4* args, JValue* pResult) //加载dex文件的过程在dvmRawDexFileOpen()和dvmJarFileOpen()方法中完成{ ...... if (dvmRawDexFileOpen(sourceName, outputName, &pRawDexFile, false) == 0) { LOGV("Opening DEX file '%s' (DEX)\n", sourceName); pDexOrJar = (DexOrJar*) malloc(sizeof(DexOrJar)); pDexOrJar->isDex = true; pDexOrJar->pRawDexFile = pRawDexFile; } else if (dvmJarFileOpen(sourceName, outputName, &pJarFile, false) == 0) { LOGV("Opening DEX file '%s' (Jar)\n", sourceName); pDexOrJar = (DexOrJar*) malloc(sizeof(DexOrJar)); pDexOrJar->isDex = false; pDexOrJar->pJarFile = pJarFile; } else { LOGV("Unable to open DEX file '%s'\n", sourceName); dvmThrowException("Ljava/io/IOException;", "unable to open DEX file"); } ...... RETURN_PTR(pDexOrJar); }
- android PathClassLoader DexClassLoader BaseDexClassLoader
- PathClassLoader && DexClassLoader
- Android DexClassLoader/PathClassLoader 动态加载jar/APK
- Android DexClassLoader/PathClassLoader 动态加载jar/APK
- Android类加载之PathClassLoader和DexClassLoader
- PathClassLoader和DexClassLoader区别
- PathClassLoader和DexClassLoader
- PathClassLoader~DexClassLoader区别
- 【Android高级】DexClassloader和PathClassloader动态加载插件的实现
- DexClassLoader和PathClassLoader的区别
- DexClassLoader和PathClassLoader的区别
- dexclassloader与pathclassloader的区别
- DexClassLoader 和 PathClassLoader简单记录
- DexClassLoader和PathClassLoader加载Dex流程
- DexClassLoader和PathClassLoader类加载机制
- Android DexClassLoader
- android DexClassLoader 加载pak
- Android中的DexClassLoader使用
- 【资源分享】我图网、千图网、包图网VIP(600套PPT模板)
- 前端js与css兼容性问题
- nginx中的函数指针的typedef
- ubuntu下安装glib库
- 数据意识上的“代沟”
- android PathClassLoader DexClassLoader BaseDexClassLoader
- 欢迎使用CSDN-markdown编辑器
- 多线程-多线程方式2的思路及代码实现
- Android之EditText设置长度限制提示和自动添加空格
- 联运游戏-支付流程
- Java程序员应该掌握的Linux知识
- android Dalvik JVM ART
- Vijos P1034 回文数
- (SqlSessionTemplate和SessionFactory)sqlsession的产生过程,hibernate和mybatis的对比