饥人谷技术博客Java

[java]一文读懂ClassLoader

2020-03-19  本文已影响0人  小贾同学coding

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

上一篇 下一篇

猜你喜欢

热点阅读