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

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

类加载器

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

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


类加载器

启动类加载器

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

    查看启动类的加载路劲

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

for (URL urL : urLs) {

    System.out.println(urL);

}

也可以通过-Xbootclasspath指定

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


加载类的存储方式

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

    双亲委派

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

            

双亲委派流程图

    打破双亲委派

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

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

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。