提个问题,为什么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的热修复?
越早越好,加载过了就会有缓存,不会再次加载