JVM随笔(二) 类加载子系统

简单来说类加载子系统 = 三层类加载 + 双亲委派

类加载器

    JVM中类加载器分为两种由C++编写的类加载器以及java编写类加载。除了启动类加载器(bootstrap class loader)是由c++编写,其余类加载器都是有java代码编写。有java编写的类加载器都继承自java.lang.ClassLoader。 java中还支持自定义类加载器。

    各个类加载器之间存在逻辑上的父子关系,通过parent字段关联。不同的类加载器加载不同的目录。


JVM随笔(二) 类加载子系统_第1张图片
类加载器

启动类加载器

    也就是bootstrapClassLoader,是有c++代码编写,在jvm中没有具体的实例,只有一段代码逻辑。通过java程序去查看显示的是null。因此启动类加载器无法被java程序调用。

    查看启动类的加载路劲

URL[] urLs = Launcher.getBootstrapClassPath().getURLs();

for (URL urL : urLs) {

    System.out.println(urL);

}

也可以通过-Xbootclasspath指定

    查看类加载器加载的类存放方式


JVM随笔(二) 类加载子系统_第2张图片
加载类的存储方式

    在方法区中,每个类加载器都有一块专属专属区域,存储该加载器加载的InstanceKlass实例,对应的InstanceMirrorKlass存储在堆中,因此,不同的类加载器加载的相同的.class文件,由于在方法区中存储的位置不同,所以加载的Class对象也是不同的。

    双亲委派

        类加载器加载一个类是,首先不自己加载,而是委派给其父类去加载,如果父类无法加载,则尝试自己去加载。双亲委派机制属于向上委派。

            

JVM随笔(二) 类加载子系统_第3张图片
双亲委派流程图

    打破双亲委派

        由于双亲委派属于向上委派,所以打破双亲委派的方式有两种,一种是不委派,直接自己加载,另一种是向下委派。

        因为在某些情况下父类加载器需要委托子类加载器去加载class文件。受到加载范围的限制,父类加载器无法加载到需要的文件,以Driver接口为例,由于Driver接口定义在jdk当中的,而其实现由各个数据库的服务商来提供,比如mysql的就写了MySQL Connector,那么问题就来了,DriverManager(也由jdk提供)要加载各个实现了Driver接口的实现类,然后进行管理,但是DriverManager由启动类加载器加载,只能加载JAVA_HOME的lib下文件,而其实现是由服务商提供的,由系统类加载器加载,这个时候就需要启动类加载器来委托子类来加载Driver实现,从而破坏了双亲委派。

你可能感兴趣的:(JVM随笔(二) 类加载子系统)