当前位置: 代码迷 >> 综合 >> Java_ClassLoader(ClassLoader / 自定义ClassLoader / DexClassLoader)
  详细解决方案

Java_ClassLoader(ClassLoader / 自定义ClassLoader / DexClassLoader)

热度:21   发布时间:2023-12-20 21:40:42.0

Java_ClassLoader(ClassLoader / 自定义ClassLoader / DexClassLoader)


本文由 Luzhuo 编写,转发请保留该信息.
原文: http://blog.csdn.net/rozol/article/details/77758194


ClassLoader 用来动态加载class文件到内存中使用的
ClassLoader 使用 双亲委托模型 来搜索类的
ClassLoader 在Android中有两个子类来加载.dex文件, 分别是 DexClassLoader / PathClassLoader
DexClassLoader 可以加载 jar / apk(未安装/已安装) / dex
PathClassLoader 只可以加载 系统中已安装的apk

原理

/*** ClassLoader* ClassLoader用来动态加载class文件到内存中使用的;* JVM并不会一次性加载程序的所有class文件, 而是根据所需加载.* * * Java内置的ClassLoader* BootStrap ClassLoader 启动类加载器 (c++编写, 嵌于JVM内核), 负责加载jdk的核心库类 (@Code = printBootStrapClassPath())* Extension ClassLoader 扩展类加载器 (Java编写, 继承于ClassLoader), 负责加载Java的扩展类库,默认加载JAVA_HOME/jre/lib/ext/目下的所有jar (@Code = printExtensionClassPath())* App ClassLoader 应用程序(系统)类加载器 (Java编写, 继承于ClassLoader), 负责加载应用程序classpath目录下的所有jar和class文件 (@Code = printAppClassPath())* * * ClassLoader原理 (@Code = classLoaderMod())* 使用 `双亲委托模型` 来搜索类* 每个ClassLoader都有一个父类加载器的引用, 如下所示, BootStrap ClassLoader 没有父类加载器, 可作为其他ClassLoader的父类加载器* *  启动类加载器 (BootStrap ClassLoader)*      ↑*  扩展类加载器 (Extension ClassLoader)*      ↑*  应用程序(系统)类加载器 (App ClassLoader)*      ↑*  自定义类加载器 (<? extend ClassLoader>)* * 当ClassLoader需要加载某个类时, 从 BootStrap ClassLoader 开始检索, 如果没有找到则从Extension ClassLoader 检索, 同理依次传递, 如果都没有, 则麻烦委托者自己从文件或网络检索, 还是没有则抛 ClassNotFoundException 异常.* 如果某个类加载器找到该类文件, 则将其生成类的定义, 加载到内存当中, 返回实例对象.* 如果该类已经存在缓存中, 类加载器将不再去检索, 而是将缓存中的类返回.* * 该模式的好处: 从上到下依次检索, 避免了 恶意代码冒充系统类代码 安全隐患;* 因为类加载器只要从自家的类加载中检索到所需的系统代码, 就不会执行用户写的类加载器, 从而避免被调包* * * 判断两个类是否相同?* 如果两个类的 全类名 相同, 且被同一个类加载器加载的, 即为同一个class;* 如果两个类的 全类名 相同, 但被非同一个类加载器加载的, 即为非同一个class.* * @author Luzhuo*/
public class Test{public static void main(String[] args) throws ClassNotFoundException, Exception {// 输出 BootStrap ClassLoader 加载的文件路径printBootStrapClassPath();// 输出 Extension ClassLoader 加载的文件路径printExtensionClassPath();// 输出 App ClassLoader 加载的文件路径printAppClassPath();// 双亲委托模型classLoaderMod();}/*** 输出BootStrap ClassLoader 加载的文件路径*/private static void printBootStrapClassPath(){// 方式1: 源码中的文件final String bootClassPath = System.getProperty("sun.boot.class.path");System.out.println("BootStrap ClassLoader - path: " + bootClassPath);// 方式2: 类提供的方法URL[] urls = Launcher.getBootstrapClassPath().getURLs();for (int i = 0; i < urls.length; i++) {System.out.println(urls[i].toExternalForm()); }}/*** 输出 Extension ClassLoader 加载的文件路径*/private static void printExtensionClassPath(){final String extensionClassPath = System.getProperty("java.ext.dirs");System.out.println("Extension ClassLoader - path: " + extensionClassPath);}/*** 输出 App ClassLoader 加载的文件路径*/private static void printAppClassPath(){final String appClassPath = System.getProperty("java.class.path");System.out.println("App ClassLoader - path: " + appClassPath);}/*** 双亲委托模型* ClassLoader原理 (Code = classLoaderMod())*/private static void classLoaderMod(){ClassLoader loader = Test.class.getClassLoader(); while(loader != null) {  System.out.println("classLoaderMod: " + loader);loader = loader.getParent(); // 获取父类加载器  }// classLoaderMod: sun.misc.Launcher$AppClassLoader@73d16e93// classLoaderMod: sun.misc.Launcher$ExtClassLoader@15db9742// BootStrap ClassLoader 为C++所写, 故未打印}
}

源码

双亲委托模型
public abstract class ClassLoader {protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{synchronized (getClassLoadingLock(name)) {// First, check if the class has already been loaded// ↓↓↓Class<?> c = findLoadedClass(name);if (c == null) {long t0 = System.nanoTime();try {if (parent != null) {// ↓↓↓c = parent.loadClass(name, false);} else {// ↓↓↓c = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {// ClassNotFoundException thrown if class not found// from the non-null parent class loader}if (c == null) {// If still not found, then invoke findClass in order// to find the class.long t1 = System.nanoTime();
  相关解决方案