jvm的双亲委派机制及作用

jvm的双亲委派机制及作用

什么是双亲委派机制

当某个类加载器需要加载某个**.class文件时,它首先把这个任务委托给他的上级类加载器**,递归这个操作,如果上级的类加载器没有加载,自己才会去加载这个类,有就加载。

类加载器可分为两类

  • 一是启动类加载器(Bootstrap ClassLoader),是C++实现的,是JVM的一部分;
  • 另一种是其它的类加载器,是Java实现的,独立于JVM,全部都继承自抽象类java.lang.ClassLoader。
  • jdk自带了三种类加载器,分别是启动类加载器(Bootstrap ClassLoader),扩展类加载器(Extension ClassLoader),应用程序类加载器(Application ClassLoader)。后两种加载器是继承自抽象类java.lang.ClassLoader

类加载器是有层次的

一般是: 自定义类加载器 >> 应用程序类加载器 >> 扩展类加载器 >> 启动类加载器
上面的层次关系被称为双亲委派模型(Parents Delegation Model)。除了最顶层的启动类加载器外,其余的类加载器都有对应的父类加载器。
再简单说下双亲委托机制:
如果一个类加载器收到了类加载的请求,它首先不会自己尝试去加载这个类,而是把这个请求委派给父类加载器,每一个层次的类加载器都是加此,因此所有的加载请求最终到达顶层的启动类加载器,只有当父类加载器反馈自己无法完成加载请求时(指它的搜索范围没有找到所需的类),子类加载器才会尝试自己去加载。

测试是否能自定义java.lang.System类

测试代码没用自定义java.lang.System类,因为测试代码用到了JDK自带的System类进行输出打印,会冲突,所以改用为自定义的java.lang.Math类。如果自定义的Math类能加载,那么自定义的System类同样能加载。
我们先直接运行下Math类,输出如下:

java.lang.NoSuchMethodError: main
Exception in thread "main" 
  • 提示Math类没有main方法。首先大家要明白一个概念,当类首次主动使用时,必须进行类的加载,这部分工作是由类加载器来完成的。根据双亲委托原则,Math类首先由启动类加载器去尝试加载,很显然,它找到rt.jar中的java.lang.Math类并加载进内存并不会加载我们自定义的Math类),然后执行main方法时,发现java.lang.Math类不存在该方法,所以报方法不存在错误。也就是说,默认情况下JVM不会加载我们自定义的Math类
  • 直接查看抽象类java.lang.ClassLoader的preDefineClass方法代码,可以看到代码就写了如果加载的类全名称以“java.”开头时,将会抛出SecurityException,这也是为什么直接执行MyMath类会出现SecurityException。
    照这样,我们自定义的类加载器必须继承自ClassLoader,其loadClass()方法里调用了父类的defineClass()方法,并最终调到preDefineClass()方法,因此我们自定义的类加载器也是不能加载以“java.”开头的java类的。

这个详细,很猛

猜你喜欢

转载自blog.csdn.net/code_mzh/article/details/106844091