当前位置: 首页 > news >正文

JVM类加载中的双亲委派机制

【1】什么是双亲委派

Java虚拟机对class文件采用的是按需加载的方式,也就是说当需要使用该类时才会将它的class文件加载到内存生成class对象。而且加载某个类的class文件时,Java虚拟机采用的是双亲委派模式,即把请求交由父类处理,它是一种任务委派模式。

在这里插入图片描述

工作原理

  • 如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行;
  • 如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器;
  • 如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此加载任务,子加载器才会尝试自己去加载,这就是双亲委派模式。

在这里插入图片描述

【2】双亲委派机制举例

如下所示,我们想要加载jdbc.jar中的类。

  • 加载jdbc.jar 用于实现数据库连接的时候会首先去java.sql下加载需要的类和接口
  • 双亲委派给引导类加载器加载需要的类和接口
  • 部分实现类是第三方厂商提供故而反向委派给系统类加载器加载

在这里插入图片描述

【3】沙箱安全机制

我们首先自定义一个java.lang.String ,编写main方法进行测试:

public class String {static{System.out.println("我是自定义的String类的静态代码块");}//错误: 在类 java.lang.String 中找不到 main 方法public static void main(String[] args) {System.out.println("hello,String");}
}

会报错如下:

错误: 在类 java.lang.String 中找不到 main 方法, 请将 main 方法定义为:public static void main(String[] args)
否则 JavaFX 应用程序类必须扩展javafx.application.Application

解释: 采用双亲委派机制,引导类加载器会加载核心类库中的String(rt.jar包中java\lang\String.class),其是没有main方法的。

那如何定义一个核心类库不存在的类呢,比如下面示例:

public class Jane {public static void main(String[] args) {System.out.println("hello!");}
}

将会报错如下: 也就是不允许你使用java.lang这个包名。

java.lang.SecurityException: Prohibited package name: java.langat java.lang.ClassLoader.preDefineClass(ClassLoader.java:655)at java.lang.ClassLoader.defineClass(ClassLoader.java:754)at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)at java.net.URLClassLoader.defineClass(URLClassLoader.java:468)at java.net.URLClassLoader.access$100(URLClassLoader.java:74)at java.net.URLClassLoader$1.run(URLClassLoader.java:369)at java.net.URLClassLoader$1.run(URLClassLoader.java:363)at java.security.AccessController.doPrivileged(Native Method)at java.net.URLClassLoader.findClass(URLClassLoader.java:362)at java.lang.ClassLoader.loadClass(ClassLoader.java:418)at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355)at java.lang.ClassLoader.loadClass(ClassLoader.java:351)at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:495)
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" 

上面这种保护机制就是沙箱安全机制,可以保护java核心类库。

【4】双亲委派机制的优势

通过上面的例子,我们可以知道,双亲机制可以

  • 避免类的重复加载
  • 保护程序安全,防止核心API被随意篡改
    • 自定义类:java.lang.String
    • 自定义类:java.lang.Jane(报错:阻止创建 java.lang开头的类)

【5】如何判断两个class对象是否相同

在JVM中表示两个class对象是否为同一个类存在两个必要条件:

  • 类的完整类名必须一致,包括包名。
  • 加载这个类的ClassLoader(指ClassLoader实例对象)必须相同。

换句话说,在JVM中,即使这两个类对象(class对象)来源同一个Class文件,被同一个虚拟机所加载,但只要加载它们的ClassLoader实例对象不同,那么这两个类对象也是不相等的。

JVM必须知道一个类型是由启动加载器加载的还是由用户类加载器加载的。如果一个类型是由用户类加载器加载的,那么JVM会将这个类加载器的一个引用作为类型信息的一部分保存在方法区中。当解析一个类型到另一个类型的引用的时候,JVM需要保证这两个类型的类加载器是相同的。

【6】类的主动使用和被动使用

Java程序对类的使用方式分为:王动使用和被动使用。

主动使用,又分为七种情况:

  • 创建类的实例
  • 访问某个类或接口的静态变量,或者对该静态变量赋值
  • 调用类的静态方法
  • 反射(比如:Class.forName(“XXXXXX”))
  • 初始化一个类的子类
  • Java虚拟机启动时被标明为启动类的类
  • JDK7开始提供的动态语言支持:java.lang.invoke.MethodHandle实例的解析结果REF_getStatic、REF_putStatic、REF_invokeStatic句柄对应的类没有初始化,则初始化

除了以上七种情况,其他使用Java类的方式都被看作是对类的被动使用,都不会导致类的初始化。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 智能闹钟能改善睡眠质量吗
  • vue使用响应式API和页面组件ref相同名称问题
  • mysql操作(进阶)
  • 第十二章 元数据管理10分
  • 【C语言】数组与指针常见笔试题讲解(1)
  • MySQL 5.7使用 GTID 和 Binlog高可用方案
  • Nginx 常用配置
  • ctfshow-web入门-sql注入(web186-web190)
  • python后端 启用 gzip 压缩响应体
  • 虚拟DOM、Vue渲染流程
  • Python3 爬虫 数据抓包
  • 【深入剖析】Spring依赖注入的最佳实践(@Autowired的正确用法)
  • 【RabbitMQ】直连交换机_扇形交换机_主题交换机
  • Vision Pro 3D 目标跟踪实战案例:厨房场景应用
  • QTableView使用示例-Qt模型视图代理(Model-View-Delegate)使用示例
  • 345-反转字符串中的元音字母
  • angular2开源库收集
  • bearychat的java client
  • Java的Interrupt与线程中断
  • Java新版本的开发已正式进入轨道,版本号18.3
  • Linux中的硬链接与软链接
  • Map集合、散列表、红黑树介绍
  • PaddlePaddle-GitHub的正确打开姿势
  • vue-cli在webpack的配置文件探究
  • WordPress 获取当前文章下的所有附件/获取指定ID文章的附件(图片、文件、视频)...
  • 前端面试之闭包
  • 使用 @font-face
  • 微信端页面使用-webkit-box和绝对定位时,元素上移的问题
  • 这几个编码小技巧将令你 PHP 代码更加简洁
  • 宾利慕尚创始人典藏版国内首秀,2025年前实现全系车型电动化 | 2019上海车展 ...
  • ​LeetCode解法汇总1276. 不浪费原料的汉堡制作方案
  • ​ssh免密码登录设置及问题总结
  • ​无人机石油管道巡检方案新亮点:灵活准确又高效
  • "无招胜有招"nbsp;史上最全的互…
  • # AI产品经理的自我修养:既懂用户,更懂技术!
  • ###C语言程序设计-----C语言学习(3)#
  • #pragma multi_compile #pragma shader_feature
  • (52)只出现一次的数字III
  • (DFS + 剪枝)【洛谷P1731】 [NOI1999] 生日蛋糕
  • (Matalb时序预测)WOA-BP鲸鱼算法优化BP神经网络的多维时序回归预测
  • (第30天)二叉树阶段总结
  • (附源码)springboot助农电商系统 毕业设计 081919
  • (每日一问)基础知识:堆与栈的区别
  • (十八)用JAVA编写MP3解码器——迷你播放器
  • (四)js前端开发中设计模式之工厂方法模式
  • (五) 一起学 Unix 环境高级编程 (APUE) 之 进程环境
  • (终章)[图像识别]13.OpenCV案例 自定义训练集分类器物体检测
  • (转)setTimeout 和 setInterval 的区别
  • (转载)Linux网络编程入门
  • ***检测工具之RKHunter AIDE
  • ../depcomp: line 571: exec: g++: not found
  • .net 7 上传文件踩坑
  • .Net FrameWork总结
  • .NET Micro Framework 4.2 beta 源码探析
  • .Net 基于.Net8开发的一个Asp.Net Core Webapi小型易用框架