JVM

JVM的三种类加载器和双亲委派机制


JVM中的类的加载器主要有三种:启动类加载器,拓展类加载器,应用类加载器。

     启动类加载器(Bootstrap classLoader):又称为引导类加载器,由C++编写,无法通过程序得到。主要负责加载JAVA中的 一些核心类库,主要是位于<JAVA_HOME>/lib/rt.jar中。

     拓展类加载器(Extension classLoader):主要加载JAVA中的一些拓展类,位于<JAVA_HOME>/lib/ext中,是启动类加载器的子类。

     应用类加载器(System classLoader): 又称为系统类加载器,主要用于加载CLASSPATH路径下我们自己写的类,是拓展类加载器的子类。

验证:

public class Hello {
    public static void main(String[] args) {
        Object object=new Object();//系统类 位于rt.jar中
        Hello hello=new Hello();// 我们自定义的类
        System.out.println(object.getClass().getClassLoader());
        System.out.println(hello.getClass().getClassLoader());
        System.out.println(hello.getClass().getClassLoader().getParent());
        System.out.println(hello.getClass().getClassLoader().getParent().getParent());
    }
}
null
sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@1540e19d
null

.getClassLoader().getParent().getParent()与object.getClass().getClassLoader()得到将会是Null,因为启动类(Bootstrap classLoader))加载器是用C++写的,我们无法通过程序直接得到.


双亲委派

双亲委派的意思是如果一个类加载器需要加载类,那么首先它会把这个类请求委派给父类加载器去完成,每一层都是如此。一直递归到顶层,当父加载器无法完成这个请求时,子类才会尝试去加载。

双亲委派有啥好处呢?

它使得类有了层次的划分。就拿java.lang.Object来说,你加载它经过一层层委托最终是由Bootstrap ClassLoader来加载的,也就是最终都是由Bootstrap ClassLoader去找<JAVA_HOME>\lib中rt.jar里面的java.lang.Object加载到JVM中。

这样如果有不法分子自己造了个java.lang.Object,里面嵌了不好的代码,如果我们是按照双亲委派模型来实现的话,最终加载到JVM中的只会是我们rt.jar里面的东西,也就是这些核心的基础类代码得到了保护。因为这个机制使得系统中只会出现一个java.lang.Object。不会乱套了。你想想如果我们JVM里面有两个Object,那岂不是天下大乱了。

  • 作者:低调做个路人 (扫码联系作者)
  • 发表时间:2019-12-07 15:57:36
  • 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)
  • 评论