ClassLoader简单分析

文章讲述了Java程序如何在没有显式类加载器的情况下运行,重点介绍了JVM内置的三个类加载器:引导类加载器、扩展类加载器和系统类加载器。同时讨论了Android系统中类加载器的应用,如SystemServer进程的启动方式和类加载器的隔离机制。最后提到类加载器的作用和热修复的时机。
摘要由CSDN通过智能技术生成

提个问题,为什么java程序没有类加载器也能运行?

在Java中,类加载器(ClassLoader)是一个非常重要的组件,它负责将.class文件加载到JVM中。然而,当你写Java程序并运行它时,你可能并没有显式地创建或使用类加载器,这是因为JVM在后台为你做了这个工作。

当你运行Java程序时,JVM会自动使用三个内置的类加载器:

1. 引导类加载器(Bootstrap ClassLoader):这是最顶层的加载类,负责加载JDK内部的核心类库,如rt.jar、resources.jar、charsets.jar等。

2. 扩展类加载器(Extension ClassLoader):这是引导类加载器的子类,负责加载JDK的扩展库。

3. 系统类加载器(System ClassLoader,也称为应用类加载器):这是扩展类加载器的子类,负责加载环境变量classpath或者系统属性java.class.path指定路径下的类库。

所以,即使你在编写Java程序时没有显式地使用类加载器,JVM在运行你的程序时仍然会使用这些内置的类加载器来加载所需的类。因此,你的程序可以正常运行。

二问 Android SystemServer 进程启动,靠反射执行main函数是因为 类加载器不同吗

是的,Android SystemServer 进程启动时会通过反射执行 main 函数,其中一个原因就是因为类加载器不同。在 Android 系统中,SystemServer 是运行在系统进程中的,它负责启动和管理系统的核心服务。为了隔离不同的应用和系统组件,Android 使用了不同的类加载器。

SystemServer 进程使用的是 BootClassLoader,它是应用程序和系统组件共享的类加载器。而普通应用程序使用的是 PathClassLoader,它只能加载应用程序的类和资源。由于 SystemServer 进程和普通应用程序使用的类加载器不同,因此无法直接调用 SystemServer 的 main 函数。为了解决这个问题,Android 使用了反射机制来调用 SystemServer 的 main 函数,

类加载器是如何判定两个类是重复的?

类加载器是通过类的全限定名和类加载器实例来判定两个类是否重复。当加载一个类时,类加载器会首先检查该类是否已经被加载过了。它会根据类的全限定名在加载器的缓存中查找该类,如果找到了对应的类,则直接返回该类的Class对象;如果没有找到,则继续加载该类。

不同的类加载器实例有自己的命名空间,它们相互之间是隔离的。所以,即使两个类的全限定名相同,但如果它们是由不同的类加载器加载的,它们仍然被认为是不同的类。

每一个 ZygtonInit都会创建一个类加载器嘛?

是的,每次调用 ZygoteInit 类的构造函数都创建一个新的类加载器。这是因为在 Android 系统的 Zygote 进程中,每个应用程序都在独立的虚拟机实例中运行,而每个虚拟机实例都有自己的类加载器。这样可以确保应用程序之间的隔离性,并且每个应用程序可以加载和运行自己的类和资源

Android的类加载器 

    /**
69       * @hide
70       */
71      public BaseDexClassLoader(String dexPath, File optimizedDirectory,
72              String librarySearchPath, ClassLoader parent, boolean isTrusted) {
73          super(parent);
74          this.pathList = new DexPathList(this, dexPath, librarySearchPath, null, isTrusted);
75  
76          if (reporter != null) {
77              reportClassLoaderChain();
78          }
79      }
     @Override
130      protected Class<?> findClass(String name) throws ClassNotFoundException {
131          List<Throwable> suppressedExceptions = new ArrayList<Throwable>();
132          Class c = pathList.findClass(name, suppressedExceptions);
133          if (c == null) {
134              ClassNotFoundException cnfe = new ClassNotFoundException(
135                      "Didn't find class \"" + name + "\" on path: " + pathList);
136              for (Throwable t : suppressedExceptions) {
137                  cnfe.addSuppressed(t);
138              }
139              throw cnfe;
140          }
141          return c;
142      }
143  
    public Class<?> findClass(String name, List<Throwable> suppressed) {
485          for (Element element : dexElements) {
486              Class<?> clazz = element.findClass(name, definingContext, suppressed);
487              if (clazz != null) {
488                  return clazz;
489              }
490          }
491  
492          if (dexElementsSuppressedExceptions != null) {
493              suppressed.addAll(Arrays.asList(dexElementsSuppressedExceptions));
494          }
495          return null;
496      }

Zygote在main函数里会初始化BootClassLoader加载器

SystemServer在main函数里创建PathClassLoader加载器

ClassLoader的parent 哪里来的?

ClassLoader的parent是在构造函数传递进入,传递进来后

会先看看父类有没有如果没有就自己加载

ClassLoader的作用是什么?

将类的字节码加载到内存中,那么当一个应用已经运行了,就没有办法再次加载了,但是等应用下次启动还可以进行加载

那么什么时候进行classLoader的热修复?

越早越好,加载过了就会有缓存,不会再次加载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值