ClassLoader类加载的示例分析
发表于:2025-01-23 作者:千家信息网编辑
千家信息网最后更新 2025年01月23日,这篇文章主要介绍了ClassLoader类加载的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。Java类加载器1、BootCl
千家信息网最后更新 2025年01月23日ClassLoader类加载的示例分析
这篇文章主要介绍了ClassLoader类加载的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。
Java类加载器
1、BootClassLoader: 用于加载Android Framework层class文件。
2、PathClassLoader: 用于Android应用程序类加载器。可以加载指定的dex,jar、zip、zpk中的classes.dex
3、DexClassLoader:加载指定的dex,以及jar、zip、apk中的classes.dex
源码解析
1.ClassLoader中提供loadClass用于加载指定类
//ClassLoader.javapublic Class> loadClass(String name) throws ClassNotFoundException { //该处调用了两个参数的重载方法 return loadClass(name, false); } protected Class> loadClass(String name, boolean resolve) throws ClassNotFoundException { //先查一下该类是否已经加载过了 Class> c = findLoadedClass(name); if (c == null) { try { //双亲委托机制,先让爸爸去找 if (parent != null) { c = parent.loadClass(name, false); } else { //如果parent为null,则用BootClassLoader进行加载 c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader } if (c == null) { //如果都找不到就自己去找,此方法在子类BaseDexClassLoader类中有重写 c = findClass(name); } } return c; }
2.BaseDexClassLoader类中对findClass有重写,也是实际会使用执行的
//BaseDexClassLoader.java//查找class @Override protected Class> findClass(String name) throws ClassNotFoundException { ... //这里通过pathList变量来查找,而pathList是在BaseDexClassLoader的构造方法中初始化的 Class c = pathList.findClass(name, suppressedExceptions); ... return c; } private final DexPathList pathList;public BaseDexClassLoader(String dexPath, File optimizedDirectory, String librarySearchPath, ClassLoader parent, boolean isTrusted) { super(parent); //构造方法中初始化pathList变量 this.pathList = new DexPathList(this, dexPath, librarySearchPath, null, isTrusted); }
3.BaseDexClassLoader中是通过调用DexPathList中的findClass来实现的,那么接下来我们分析一下DexPathList是怎么实现的
//DexPathList.java//是一个Element数组,一个element中包含一个 DexFile,DexFile就代表一个Dex文件,里面的native(C/C++)函数来进行Dex的加载工作 private Element[] dexElements; public Class> findClass(String name, Listsuppressed) { for (Element element : dexElements) { //此处调用Element的findClass来实现, Class> clazz = element.findClass(name, definingContext, suppressed); if (clazz != null) { return clazz; } } return null; }// Element为DexPathList的内部类static class Element { private final File path; //一个DexFile就代表一个Dex文件 private final DexFile dexFile; //有多个构造方法,但都仅是将值传过来,让Element来持有一个DexFile public Element(DexFile dexFile) { this.dexFile = dexFile; this.path = null; } public Class> findClass(String name, ClassLoader definingContext, List suppressed) { //通过DexFile来加载类 return dexFile != null ? dexFile.loadClassBinaryName(name, definingContext, suppressed) : null; } }DexPathList(ClassLoader definingContext, String dexPath, String librarySearchPath, File optimizedDirectory, boolean isTrusted) { //通过makeDexElements方法为dexElements初始化 this.dexElements = makeDexElements(splitDexPath(dexPath), optimizedDirectory, suppressedExceptions, definingContext, isTrusted);}//腾讯系的热修复,诸如微信tinker、qq空间qfix原理便是反射此方法,将修复后的类打包成dex,通过反射该方法来将文件转化为Element,并将新生成的element放到dexElements前面,这样下次系统再去寻找某个class时,会先从修复后的dex中来找class,找到后便不再继续查找,从而修复该class,此方式便为插桩private static Element[] makeDexElements(List files, File optimizedDirectory, List suppressedExceptions, ClassLoader loader, boolean isTrusted) { Element[] elements = new Element[files.size()]; ... for (File file : files) { if (name.endsWith(DEX_SUFFIX)) { //以 .dex 结尾的 // Raw dex file (not inside a zip/jar). //加载dex文件 dex = loadDexFile(file, optimizedDirectory, loader, elements); if (dex != null) { elements[elementsPos++] = new Element(dex, null); } } } ... return elements; }private static DexFile loadDexFile(File file, File optimizedDirectory, ClassLoader loader, Element[] elements) throws IOException { if (optimizedDirectory == null) { return new DexFile(file, loader, elements); } else { String optimizedPath = optimizedPathFor(file, optimizedDirectory); return DexFile.loadDex(file.getPath(), optimizedPath, 0, loader, elements); } }
4.这里通过 new DexFile 或者 loadDex方法来创建DexFile,两者类似,那我们拿new DexFile 来举例分析
//DexFile.javaprivate DexFile(String sourceName, String outputName, int flags, ClassLoader loader, DexPathList.Element[] elements) throws IOException { ... //此处调用openDexFile来实现 mCookie = openDexFile(sourceName, outputName, flags, loader, elements); ... }private static Object openDexFile(String sourceName, String outputName, int flags, ClassLoader loader, DexPathList.Element[] elements) throws IOException { //此处通过调用 openDexFileNative来实现 return openDexFileNative(new File(sourceName).getAbsolutePath(), (outputName == null) ? null : new File(outputName).getAbsolutePath(), flags, loader, elements); }//openDexFileNative是一个native方法,是由C/C++来实现的private static native Object openDexFileNative(String sourceName, String outputName, int flags, ClassLoader loader, DexPathList.Element[] elements);
感谢你能够认真阅读完这篇文章,希望小编分享的"ClassLoader类加载的示例分析"这篇文章对大家有帮助,同时也希望大家多多支持,关注行业资讯频道,更多相关知识等着你来学习!
方法
文件
分析
篇文章
示例
代表
变量
此方法
反射
接下来
两个
价值
兴趣
函数
原理
参数
双亲
同时
多个
子类
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
达内网络安全教育
网络安全的英文看法
大学网络安全工程师需要学什么
泉州软件开发哪里招工
数据库有几种基本类型
佳缘科技互联网医院
上海明咨网络技术有限公司
bigant服务器
mysql数据库基础知识笔记
国家网络安全三队
网络安全的实习生工资
数据库论文答辩流程
叔叔不约服务器连接不上
聊城手机软件开发哪家便宜
成都苹果软件开发大概多少钱
安全防控软件开发合同书
网络安全法互联网保护义务
光馨网络技术
网络安全和信息化工作会
万能web服务器做什么
服务器控件的利弊
云海麒麟服务器管理口ip
如何利用服务器赚钱
个人软件开发兼职
电视可以下载网络安全吗
做好的数据库怎么分离
app软件开发工程师工资
服务器电源ac灯亮但是开不了机
计算机网络技术属于什么行业
po软件开发