ClassLoader类加载器原理解析
首先的了解下我们的类加载器 - 类加载器就是把我们的.class文件加载到JVM中生成对应的Class对象
1.BootStrapClassLoader - 这个类是我们JVM的类(OpenJDK)C++写的,它负责加载我们JRE lib下面的核心类库如rt.jar - 也就是我们的lang和util等等包下的类(String。。)
2. ExtClassLoader - 这个类是负责加载我们ext包下面的类
3. AppClassLoader - 负责加载我们APP(一般是classpath)下面的类
4. CustomerClassLoader - 程序员自定义的类加载器
当一个类加载器去加载一个Class文件的时候默认情况下并不会自己去加载而是由父类加载器去加载,当父类加载器发现类不是自己加载的范畴就会让子类去加载 - 这个机制就是网上的双亲委派 - 个人觉得叫父类委托,哪来的双亲?
上面的机制就会保证一个Class文件只会被一个类加载器加载(同时也保证在系统中一个Class对象只会存在一份),而且只会被加载一次,因为当ClassLoader加载一个class文件后会在本地缓存(下面源码解析会说到)一个Class的引用,当再次加载这个Class文件的时候会去本地引用找,找到直接return就不会在加载。
如果同一个Class被2个ClassLoader加载(这种情况下只会发生在程序员自定义的类加载)他们的类型是不同的,相互转化的时候会报错
A a = ClassLoaderA.load
A b = ClassLoaderB.load
a = b 会报错
考虑一个问题自己写一个String类会不会被加载?
1.如果自己定义个String类而且包名是java.lang这个String类是不会被加载的
-通过双亲委派机制,这个类会被BootStrapClassLoader加载,但是它会去先加载我们核心类库(JRE lib包下的rt.jar里面的java.lang.String),由于缓存,它不会再加载我们的这个java.lang.String
2.如果随意包名就会被加载。
类加载器加载原理(源码分析)
ClassLoader - 这是我们的顶级父类,Ext 和App两个classloader都是它的子类
1.ClassLoader里面有一个ClassLoader的一个属性来维护parent关系的
2.loadClass(String name) - 通过类名来
3.this.findLoadedClass(name) -首先去本地缓存(里面调用的一个native方法,说明缓存是在JVM中的)去找,找到就返回,找不到继续
4.if (this.parent !=null) {
c =this.parent.loadClass(name, false);
}else {
c =this.findBootstrapClassOrNull(name);
} - 这就是双亲委派机制,- 这里也是个递归调用。
5.if (c ==null) {
c =this.findClass(name);
} - 如果父类返回null(没有加载这个class)就调用自己的findClass方法加载