1.什么是classLoader
先来看一个概念,Class对象。什么是class对象呢?Java中用来表示运行时类型信息的对应类就是Class类,而Class对象就是Class所创建的一个实例,注意这里的Class类是实实在在的一个类,在java.lang包下。Class类的作用就是在运行时描述一个类的对象的类型和和类的信息,从而达到RTTI(RUNTIME TYPE IDENTIFICATION)运行时类型识别。java中的运行时类型识别有两种方式。一是编译时已确定的类型,例如
List<Shape> shapeList = Arrays.asList(new Circle(), new Square(), new Triangle());
for(Shape shape : shapeList) {
shape.draw();
}
我们规定了shapeList的泛型,所以在运行期间当array中取出object对象时需要将对象转成Shape对象,需要做正确定检查,这里检查一个对象是否是Shape对象,就是在编译时已经指出的,需以Shape类型做正确性检查。
二就是反射机制,这里就不做过多的描述,因为跑题了。
而classLoader就是用来加载Class对象,将字节码形式的class转换成内存中的class对象。而字节码的本质就是一个byte[],classloader讲byte[]转换为class对象。
2.classLoader的种类
-BootstrapClassLoader(根加载器)
负责加载 java核心类
-ExtensionClassLoader ()
拓展类加载 JAVA_HOME/lib/ext/下的类
-AppClassLoader (系统类加载器)
加载我们自己的编写的程序,使用的第三方jar包等 Classpath 环境变量里定义的路径中jar包和目录。
3.classLoader的模式
-双亲委派模式
双亲委派模式 当我们的程序在运行时,碰到一个未被加载的类怎么办呢?
我们的程序会调用ClassLoader来加载这个类,那么这个类该由那种类加载呢?
jvm的策略是由调用者的ClassLoader,即发现这个未被加载的类的类的ClassLoader,那么我们都知道自定义的和第三方的类是由AppClassLoader加载,那么假如这个未被加载的类是java核心类呢?是ext下的类呢?
这里就引出了双亲委派模式,AppClassLoader发现一个未被加载的类那么并不会首先交由自己加载,而是向上交由自己的parent,即ExtensionClassLoader来加载,如果它无法加载,再去寻找classpath下的类并加载;同样的ExtensionClassLoader也会向上传递给BoostStrapClassLoader,如果它无法加载再去由自己加载。双亲委派模型保障了类加载的正确性。
4.classLoader的重要方法
-Class.forName
Class.forName()的方法经常用来动态加载驱动类,如mysql;原理是对应的Driver类中有一个静态代码块,当class类被加载时会自动将驱动实例注册到驱动管理器中。
class Driver {
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
...
}
&emsp;Class.forName()的特殊之处在于它可以指定类加载器进行加载,也就是允许了我们使用自定义的加载器进行加载。
Class<?> forName(String name, boolean initialize, ClassLoader cl)
-loadClass()
加载目标类的入口
-defineClass()
将字节码转换为Class对象
-findClass()
搜寻字节码文件并调用defineClass()转换(通常由子类实现)
至此,记录结束。
这里引用一篇文章Class.forName和ClassLoader.loadClass
本文借鉴,参考。额,部分照搬老大难的 Java ClassLoader
网友评论