您的位置:首页 > 编程语言 > Java开发

浅谈Java的虚拟机JVM的类加载器和双亲委派模型理解

2018-12-06 19:06 411 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/qq_34420835/article/details/84863337

1.类加载器的分类

1)类加载器的作用:将类的字节码文件(即.class文件),加载到JVM中(即内存中)。
(引用)jvm-java 内存模型 以及各个分区具体内容:jvm-java 内存模型 以及各个分区具体内容.

2)类加载器使用时机:在我们需要使用一个类又不想创建对象的时候,还有就是当我们为了方便使用大量各种类的方法、构造器和变量的时候(这里需要配合反射方式实现)。这时候我们一般就只需要使用到类的全限定类名就可以了(这时候一般我们会配合使用到配置文件中的我们需要使用的累的全限定类名)。*

1.1引导类加载器(Bootstrap ClassLoader)

1)这个类加载器是一个使用C++编写的,用来加载核心类库中的类,也就是负责将存放在<JAVA_HOME>\lib目录或-Xbootclasspath参数指定的路径中的类库加载到内存中。

1.2其他类加载器

1)其他类加载器,使用Java编写,继承自抽象类ClassLoader,分为扩展类加载器(Extension ClassLoader)和应用程序类加载器(Application ClassLoader)。

1.2.1扩展类加载器(Extension ClassLoader)

1 )扩展类加载器加载ext包下的类,就是负责加载<JAVA_HOME>\lib\ext目录或java.ext.dirs系统变量指定的路径中的所有类库。

1.2.2应用程序类加载器(Application ClassLoader)

1)应用类程序类加载器用来加载我们自己定义的类的。就是负责加载用户类路径(classpath)上的指定类库,我们可以直接使用这个类加载器。一般情况,如果我们没有自定义类加载器默认就是用这个加载器。

2.双亲委派模型


注意:这里的父子关系是使用组合(Composition)关系而非继承(Inheritance)关系来实现的,构造函数形如new XXClassLoader(xx, ParentClassLoader)~

1)双亲委派加载就是在我们的自定义类的使用类加载器的时候,最先接受加载器委派请求的是我们的自定义类加载器,而自定义类加载器不会直接加载,而是将这个加载请求委派给它的父类加载器应用程序类加载器(Application ClassLoader),同样的应用程序类加载器也不会直接加载也是交给自己的父类加载器扩展类加载器(Extension ClassLoader),同样的扩展类加载器也是一样,将这个加载请求委派给自己的父类加载器引导类加载器(Bootstrap ClassLoader),这个时候因为引导类加载器(Bootstrap ClassLoader)已经没有父类加载器了,它就会先判断一下自己的指定范围内是否能找到这个类,如果找到了,就自己加载了,如果找不到(即ClassNotFoundException),就会将这个加载请求委派给子类加载器加载,直到子类加载器完成这个加载请求,或者所有类加载器都没有这个类的时候就会报类没有被发现异常(即ClassNotFoundException)。整个加载到此结束~

2.1双亲委派模型的作用

1)双亲委派模型的原理很简单,实现也简单。每次通过先委托父类加载器加载,当父类加载器无法加载时,再自己加载。其实ClassLoader类默认的loadClass方法已经帮我们写好了,我们无需去写。

2)如果没有双亲委派模型:自定义一个java.lang.String类,该String类具有系统的String类一样的功能,只是在某个函数稍作修改。比如equals函数,这个函数经常使用,如果在这这个函数中,加入一些“病毒代码”。并且通过自定义类加载器加入到JVM中。此时,如果没有双亲委派模型,那么JVM就可能误以为自定义的java.lang.String类是系统的String类,导致“病毒代码”被执行。

3)而有了双亲委派模型,自定义的java.lang.String类永远都不会被加载进内存。因为首先是最顶端的类加载器加载系统的java.lang.String类,最终自定义的类加载器无法加载java.lang.String类。

4)不去通过调用父加载器不就好了吗?确实,这样是可行。但是,在JVM中,判断一个对象是否是某个类型时,如果该对象的实际类型与待比较的类型的类加载器不同,那么会返回false。举个简单例子:ClassLoader1、ClassLoader2都加载java.lang.String类,对应Class1、Class2对象。 那么Class1对象不属于ClassLoad2对象加载的java.lang.String类型。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: